繁体   English   中英

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

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

我正在使用SymPy,遇到以下问题:

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

等等,不应该是sympy.utilities.lambdify是一个模块吗?

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

哦,所以有一个命名冲突。

现在显然我可以使用implemented_function ,但这不是我的问题。

我的问题是:如何导入sympy.utilities.lambdify 模块而不是函数

(我在这里只是使用SymPy进行说明。这是否适当的库使用是不重要的。来源就在这里 。)

实际上,看起来这可以用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'>

来自评论的编辑(感谢@Mehrdad):

或者,如果您想避免将模块名称放在字符串中,您可以这样做:

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

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

虽然这看起来有点长,对我来说不太清楚。

明显的不一致是由于lambdify不是一个模块,它是一个包含多个函数定义的python文件。 在名为bar.py的文件中考虑以下示例:

def foo(): pass

def bar(): pass

然后from bar import bar; print(bar.__module__) from bar import bar; print(bar.__module__)会给你'bar'

可以导入lambdify的原因,就像这是sympy.utilities__init__sympy.utilities

from .lambdify import lambdify

也就是说,在sympy.utilities模块的lambdify.py文件中,有一个lambdify()的定义,并将其导入sympy.utilities命名空间。 因此,当您导入sympy.utilities ,您可以访问lambdify。 但是,你仍然可以import定义等功能lambdify.py通过from sympy.utilities.lambdify import ...


您的实际问题是您是否可以导入这样的模块。 嗯, 你可以 ,但你可能不应该。 让我们使用上面的bar.py对情况进行bar.py ,并通过创建__init__py使其成为一个包:

from .bar import bar

将这两个文件放在名为tmp ,我们得到一个你的场景模型,一个名为tmp的模块和一个“子模块” bar (但我不认为它是一个合适的子模块,缺少__init__.py )。 如果我们导入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>

所以tmp.bar指的是函数而不是模块。 显然。 但实际上它也提供了对模块的访问,尽管它被同名函数遮蔽了!

让我们重复上面的内容,但继续监视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>

因此,虽然tmp.bar引用了本地命名空间中的函数,但我们可以通过来自同一导入的sys.modules['tmp.bar']来访问模块本身。

只是为了明确:

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

这是针对sympy的结构。 请参阅实用程序__init__.py的源代码的这一

from .lambdify import lambdify

它导入功能 lambdify从本地模块lambdify ; 那么utilities.lambdify就是这个功能

假设您希望真正导入模块,而不是函数, lambdify 也许是这样的,

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM