Python的__import__不按预期工作
当你使用 __import__
这个函数,并且给它一个带点的名字,比如说 somepackage.somemodule
,你会发现返回的模块并不是 somemodule
,而是看起来几乎是空的东西!这是怎么回事呢?
6 个回答
这里有一个更简单的解决办法,文档里有解释:
如果你只是想通过名字导入一个模块(可能是在一个包里面),你可以使用 __import__() 函数,然后在 sys.modules 里查找它:
>>> import sys
>>> name = 'foo.bar.baz'
>>> __import__(name)
<module 'foo' from ...>
>>> baz = sys.modules[name]
>>> baz
<module 'foo.bar.baz' from ...>
Python 2.7 有一个叫做 importlib 的模块,它可以按照预期处理带点的路径。
import importlib
foo = importlib.import_module('a.dotted.path')
instance = foo.SomeClass()
来自Python文档关于__import__
的内容:
__import__( name[, globals[, locals[, fromlist[, level]]]])
...
当你使用的名字是类似于 package.module的格式时,通常会返回 顶层包(也就是第一个点之前的名字),而不是 名字所指的模块。不过,当你提供了一个 非空的fromlist参数时,就会返回 名字所指的模块。这是为了和 不同类型的导入语句生成的字节码兼容; 比如,当你使用“import spam.ham.eggs”时, 顶层包spam必须放在导入的命名空间中,但 当你使用“from spam.ham import eggs”时, 就必须使用spam.ham子包来找到 eggs变量。为了应对这种情况,可以使用 getattr()来提取所需的组件。例如,你可以 定义以下的辅助函数:
def my_import(name): mod = __import__(name) components = name.split('.') for comp in components[1:]: mod = getattr(mod, comp) return mod
换句话说:
当你请求somepackage.somemodule
时,__import__
返回的是somepackage.__init__.py
,而这个文件通常是空的。
如果你提供fromlist
(这是一个包含你想要的somemodule
内部变量名的列表,实际上这些变量不会被返回),它就会返回somemodule
。
你也可以像我一样,使用他们建议的函数。
注意:我问这个问题时,完全是打算自己回答的。我的代码里有一个大bug,我误诊了它,花了很长时间才搞明白,所以我想帮助一下SO社区,把我遇到的问题分享出来。