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()