简体   繁体   English

如何强制Python的“导入”将名称视为模块,而不是函数?

[英]How to force Python's “import” to treat name as a module, not a function?

I'm using SymPy, and encountering the following problem: 我正在使用SymPy,遇到以下问题:

>>> import sympy.utilities.lambdify
>>> sympy.utilities.lambdify
<function lambdify at 0x0000000003802B38>

Wait, shouldn't sympy.utilities.lambdify be a module? 等等,不应该是sympy.utilities.lambdify是一个模块吗?

>>> from sympy.utilities.lambdify import implemented_function
>>> implemented_function
<function implemented_function at 0x0000000003802CF8>
>>> implemented_function.__module__
'sympy.utilities.lambdify'

Oh, so there's a naming conflict. 哦,所以有一个命名冲突。

Now obviously I can just use implemented_function , but that's not my question. 现在显然我可以使用implemented_function ,但这不是我的问题。

My question is: how can I import the sympy.utilities.lambdify module rather than the function ? 我的问题是:如何导入sympy.utilities.lambdify 模块而不是函数

(I just used SymPy for illustration here. Whether or not this is proper library usage is beside the point. The source is here .) (我在这里只是使用SymPy进行说明。这是否适当的库使用是不重要的。来源就在这里 。)

Actually, it looks like this can be done quite cleanly with importlib: 实际上,看起来这可以用importlib非常干净地完成:

import importlib
lamdify = importlib.import_module('sympy.utilities.lambdify')
print lambdify
  <module 'sympy.utilities.lambdify' from 'c:\python-2.7.8-amd64\lib\site-packages\sympy\utilities\lambdify.pyc'>

EDIT from comments (thanks @Mehrdad): 来自评论的编辑(感谢@Mehrdad):

Alternatively, if you want to avoid putting module names in strings, you could do this: 或者,如果您想避免将模块名称放在字符串中,您可以这样做:

def import_module(lambda_): 
    import importlib; 
    return importlib.import_module('.'.join(lambda_.__code__.co_names)) 

Usage: lambdify = import_module(lambda: sympy.utilities.lambdify) 用法: lambdify = import_module(lambda: sympy.utilities.lambdify)

Though this looks a bit longer and less clear to me. 虽然这看起来有点长,对我来说不太清楚。

The apparent inconsistency is due to the fact that lambdify is not a module, it's a python file containing multiple function definitions. 明显的不一致是由于lambdify不是一个模块,它是一个包含多个函数定义的python文件。 Consider the following example in a file called bar.py : 在名为bar.py的文件中考虑以下示例:

def foo(): pass

def bar(): pass

Then from bar import bar; print(bar.__module__) 然后from bar import bar; print(bar.__module__) from bar import bar; print(bar.__module__) will give you 'bar' . from bar import bar; print(bar.__module__)会给你'bar'

The reason lambdify can be imported like this is the line in the __init__ of sympy.utilities : 可以导入lambdify的原因,就像这是sympy.utilities__init__sympy.utilities

from .lambdify import lambdify

That is, in the lambdify.py file of the sympy.utilities module, there's a definition for lambdify() , and this is imported into the sympy.utilities namespace. 也就是说,在sympy.utilities模块的lambdify.py文件中,有一个lambdify()的定义,并将其导入sympy.utilities命名空间。 So when you import sympy.utilities , you have access to lambdify. 因此,当您导入sympy.utilities ,您可以访问lambdify。 But you can still import other functions defined in lambdify.py by from sympy.utilities.lambdify import ... . 但是,你仍然可以import定义等功能lambdify.py通过from sympy.utilities.lambdify import ...


Your actual question is whether you can import a module like this. 您的实际问题是您是否可以导入这样的模块。 Well, you can , but you probably shouldn't. 嗯, 你可以 ,但你可能不应该。 Let's model the situation with the above bar.py , and make it a package by creating an __init__py : 让我们使用上面的bar.py对情况进行bar.py ,并通过创建__init__py使其成为一个包:

from .bar import bar

Putting these two files in the directory named tmp , we get a model of your scenario, with a module named tmp and a "submodule" bar (but I don't think it's a proper submodule, lacking an __init__.py ). 将这两个文件放在名为tmp ,我们得到一个你的场景模型,一个名为tmp的模块和一个“子模块” bar (但我不认为它是一个合适的子模块,缺少__init__.py )。 The same thing happens if we import tmp.bar , as with sympy : 如果我们导入tmp.bar就会发生同样的事情,就像在sympy

>>> import tmp
>>> tmp
<module 'tmp' from '/home/user/python/tmp/__init__.py'>
>>> import tmp.bar
>>> tmp.bar
<function bar at 0x7f24426461e0>
>>> tmp.bar.foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'foo'
>>> from tmp.bar import foo
>>> foo
<function foo at 0x7f2442646158>

So tmp.bar refers to the function rather than the module. 所以tmp.bar指的是函数而不是模块。 Apparently. 显然。 But actually it also gives access to the module, despite it being shadowed by the function of the same name! 但实际上它也提供了对模块的访问,尽管它被同名函数遮蔽了!

Let's repeat the above, but keep monitoring sys.modules : 让我们重复上面的内容,但继续监视sys.modules

>>> import sys
>>> 'tmp' in sys.modules
False
>>> import tmp.bar
>>> tmp.bar
<function bar at 0x7fc833025158>
>>> 'tmp.bar' in sys.modules
True
>>> tmp.bar.foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'foo'
>>> sys.modules['tmp.bar'].foo
<function foo at 0x7fc833020f28>

So while tmp.bar refers to the function in the local namespace, we can access the module itself through sys.modules['tmp.bar'] coming from the same import. 因此,虽然tmp.bar引用了本地命名空间中的函数,但我们可以通过来自同一导入的sys.modules['tmp.bar']来访问模块本身。

Just to be explicit: 只是为了明确:

>>> import sys
>>> import sympy.utilities.lambdify
>>> lambdify_module = sys.modules['sympy.utilities.lambdify']
>>> lambdify_module.implemented_function
<function implemented_function at 0x7fc83183ca60>

This is specific to the structure of sympy . 这是针对sympy的结构。 See this line of the source code for the utilities __init__.py : 请参阅实用程序__init__.py的源代码的这一

from .lambdify import lambdify

It imports the function lambdify from the local module lambdify ; 它导入功能 lambdify从本地模块lambdify ; thus utilities.lambdify is the function . 那么utilities.lambdify就是这个功能

Supposing that you wish to truly import the module, and not the function, lambdify . 假设您希望真正导入模块,而不是函数, lambdify Perhaps something like, 也许是这样的,

import os
import imp

import sympy.utilities as mod
sub_mod_name = 'lambdify'
sub_mod_file = '{}.py'.format(sub_mod_name)

mod_loc = os.path.dirname(mod.__file__)
file_ = os.path.join(mod_loc, sub_mod_file)  # Full path for source file
sub_mod = imp.load_source(sub_mod_name, file_)  # Import module from source file

print sub_mod
# <module 'lambdify' from '/usr/local/lib/python2.7/dist-packages/sympy/utilities/lambdify.pyc'>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 Python 3 中强制导入模块? - How to force import module in Python 3? Python将模块名称视为“NoneType” - Python treat module name as 'NoneType' 导入模块,然后导入特定功能-一种更Python化的方式来处理导入 - import module then import specific function - more pythonic way to treat import Python如何处理sys.path.insert(path)和不同地导入package_path.module - How does Python treat sys.path.insert(path) and import package_path.module differently 如何使用名称而不是文件名导入python模块 - How to import a python module with a name not the filename 如何使用 python 的 TimedRotatingFileHandler 强制旋转名称? - How to force a rotating name with python's TimedRotatingFileHandler? 在Python中,在调用函数之前强制使用模块名称 - Force use of module name before calling function, in Python 用Python的__import__函数如何等效于“从模块导入*”? - How does one do the equivalent of “import * from module” with Python's __import__ function? 如何导入站点包的模块而不是当前目录中具有相同名称的模块(python 3.x)? - How to import site package's module instead of one in current directory that has the same name (python 3.x)? Python动态导入 - 如何从变量中导入*模块名称? - Python dynamic import - how to import * from module name from variable?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM