Python的__import__不能按预期工作
当使用带有虚线名称的somepackage.somemodule
,如: somepackage.somemodule
,返回的模块不是somemodule
,无论返回什么似乎都是空的! 这里发生了什么?
从__import__
上的python文档:
__import__( name[, globals[, locals[, fromlist[, level]]]])
…
当namevariables的forms为package.module时,通常返回顶层包(名称直到第一个点),而不是由name命名的模块。 但是,如果给出非空的fromlist参数,则会返回按名称命名的模块。 这是为了与为不同types的导入语句生成的字节码兼容而完成的; 当使用“import spam.ham.eggs”时,顶级包垃圾邮件必须放置在导入的名称空间中,但在使用“from spam.ham import eggs”时,必须使用spam.ham子包来查找eggvariables。 作为这种行为的解决方法,使用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
中的variables名称列表,它实际上并没有返回),它将返回somemodule
你也可以像我一样使用他们build议的function。
注:我问了这个问题,完全打算自己回答。 我的代码有一个很大的错误,误解了它,花了很长时间才发现,所以我想我会帮助SO社区,并发布我在这里遇到的问题。
python 2.7有importlib,虚线path按预期解决
import importlib foo = importlib.import_module('a.dotted.path') instance = foo.SomeClass()
有一个更简单的解决scheme,如文档中所述:
如果你只是想按名称导入一个模块(可能在一个包内),你可以调用__import __()然后在sys.modules中查找:
>>> import sys >>> name = 'foo.bar.baz' >>> __import__(name) <module 'foo' from ...> >>> baz = sys.modules[name] >>> baz <module 'foo.bar.baz' from ...>
有一些工作是你想要的: 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'>
对于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
我做的方式是
foo = __import__('foo', globals(), locals(), ["bar"], -1) foobar = eval("foo.bar")
那么我可以通过访问任何内容
foobar.functionName()