[英]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.