Python的__import__不能按预期工作

时间:2008-10-17 04:46:09

标签: python python-import

当使用带有虚线名称的__import__时,如somepackage.somemodule,返回的模块不是somemodule,返回的内容似乎大部分都是空的!这是怎么回事?

6 个答案:

答案 0 :(得分:54)

来自__import__上的python文档:

__import__( name[, globals[, locals[, fromlist[, level]]]])
     

...

     

当name变量属于表单时   package.module,通常是   顶级包(名称直到   返回第一个点,而不是   按名称命名的模块。但是,当一个   给出了非空的fromlist参数,   返回按名称命名的模块。   这样做是为了兼容   为...生成的字节码   不同种类的进口声明;   当使用“import spam.ham.eggs”时,   必须放置顶级包垃圾邮件   在导入命名空间中,但何时   使用“来自spam.ham导入鸡蛋”,   必须使用spam.ham子包   找到蛋变量。作为一个   解决此问题的方法,使用   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,这通常是空的。

如果您提供somemodule(您想要的fromlist内的变量名称列表,但实际上并未返回),它将返回somemodule

您也可以像我一样使用他们建议的功能。

注意:我问这个问题完全打算自己回答。我的代码中有一个很大的错误,并且误解了它,我花了很长时间才弄明白,所以我想我会帮助SO社区并发布我遇到的问题。

答案 1 :(得分:32)

python 2.7具有importlib,虚线路径按预期解析

import importlib
foo = importlib.import_module('a.dotted.path')
instance = foo.SomeClass()

答案 2 :(得分:16)

有一个更简单的解决方案,如文档中所述:

如果您只想按名称导入模块(可能在包中),可以调用__import __()然后在sys.modules中查找:

>>> import sys
>>> name = 'foo.bar.baz'
>>> __import__(name)
<module 'foo' from ...>
>>> baz = sys.modules[name]
>>> baz
<module 'foo.bar.baz' from ...>

答案 3 :(得分:7)

有些内容可以按照您的意愿运行: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'>

答案 4 :(得分:1)

对于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

答案 5 :(得分:0)

我的方式是

foo = __import__('foo',  globals(), locals(), ["bar"], -1)
foobar = eval("foo.bar")

然后我可以访问

中的任何内容
foobar.functionName()