Python 的 __import__ 无法按预期工作
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/211100/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python's __import__ doesn't work as expected
提问by dwestbrook
When using __import__
with a dotted name, something like: somepackage.somemodule
, the module returned isn't somemodule
, whatever is returned seems to be mostly empty! what's going on here?
使用__import__
带点名称的名称时,例如: somepackage.somemodule
,返回的模块不是somemodule
,返回的内容似乎大多为空!这里发生了什么?
回答by dwestbrook
From the python docs on __import__
:
从 python 文档上__import__
:
__import__( name[, globals[, locals[, fromlist[, level]]]])
...
When the name variable is of the form package.module, normally, the top-level package (the name up till the first dot) is returned, not the module named by name. However, when a non-empty fromlist argument is given, the module named by name is returned. This is done for compatibility with the bytecode generated for the different kinds of import statement; when using "import spam.ham.eggs", the top-level package spam must be placed in the importing namespace, but when using "from spam.ham import eggs", the spam.ham subpackage must be used to find the eggs variable. As a workaround for this behavior, use getattr() to extract the desired components. For example, you could define the following helper:
def my_import(name): mod = __import__(name) components = name.split('.') for comp in components[1:]: mod = getattr(mod, comp) return mod
__import__( name[, globals[, locals[, fromlist[, level]]]])
...
当 name 变量的形式为 package.module 时,通常返回顶级包(直到第一个点的名称),而不是按名称命名的模块。但是,当给出非空的 fromlist 参数时,将返回按名称命名的模块。这样做是为了与为不同类型的导入语句生成的字节码兼容;使用“import spam.ham.eggs”时,顶级包spam必须放在importing命名空间中,但使用“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
To paraphrase:
转述:
When you ask for somepackage.somemodule
, __import__
returns somepackage.__init__.py
, which is often empty.
当您请求时somepackage.somemodule
,__import__
返回somepackage.__init__.py
,它通常是空的。
It will return somemodule
if you provide fromlist
(a list of the variable names inside somemodule
you want, which are not actually returned)
它将返回somemodule
如果提供fromlist
(变量名的名单里somemodule
你想要的,实际上不返回)
You can also, as I did, use the function they suggest.
您也可以像我一样使用他们建议的功能。
Note: I asked this question fully intending to answer it myself. There was a big bug in my code, and having misdiagnosed it, it took me a long time to figure it out, so I figured I'd help the SO community out and post the gotcha I ran into here.
注意:我问这个问题完全是为了自己回答。我的代码中有一个大错误,并且误诊了它,我花了很长时间才弄明白,所以我想我会帮助 SO 社区并在这里发布我遇到的问题。
回答by cerberos
python 2.7 has importlib, dotted paths resolve as expected
python 2.7 具有 importlib,虚线路径按预期解析
import importlib
foo = importlib.import_module('a.dotted.path')
instance = foo.SomeClass()
回答by Paolo
There is a simpler solution, as explained in the documentation:
有一个更简单的解决方案,如文档中所述:
If you simply want to import a module (potentially within a package) by name, you can call __import__() and then look it up in sys.modules:
如果您只是想按名称导入模块(可能在包内),您可以调用 __import__() 然后在 sys.modules 中查找它:
>>> import sys
>>> name = 'foo.bar.baz'
>>> __import__(name)
<module 'foo' from ...>
>>> baz = sys.modules[name]
>>> baz
<module 'foo.bar.baz' from ...>
回答by Glyph
There is something that works as you want it to: twisted.python.reflect.namedAny
:
有一些东西可以按您的意愿工作twisted.python.reflect.namedAny
::
>>> from twisted.python.reflect import namedAny
>>> namedAny("operator.eq")
<built-in function eq>
>>> namedAny("pysqlite2.dbapi2.connect")
<built-in function connect>
>>> namedAny("os")
<module 'os' from '/usr/lib/python2.5/os.pyc'>
回答by David Seddon
For python 2.6, I wrote this snippet:
对于 python 2.6,我写了这个片段:
def import_and_get_mod(str, parent_mod=None):
"""Attempts to import the supplied string as a module.
Returns the module that was imported."""
mods = str.split('.')
child_mod_str = '.'.join(mods[1:])
if parent_mod is None:
if len(mods) > 1:
#First time this function is called; import the module
#__import__() will only return the top level module
return import_and_get_mod(child_mod_str, __import__(str))
else:
return __import__(str)
else:
mod = getattr(parent_mod, mods[0])
if len(mods) > 1:
#We're not yet at the intended module; drill down
return import_and_get_mod(child_mod_str, mod)
else:
return mod
回答by rahul mishra
The way I did is
我的做法是
foo = __import__('foo', globals(), locals(), ["bar"], -1)
foobar = eval("foo.bar")
then i can access any content from by
然后我可以访问任何内容
foobar.functionName()