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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 19:38:45  来源:igfitidea点击:

Python's __import__ doesn't work as expected

pythonpython-import

提问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 somemoduleif you provide fromlist(a list of the variable names inside somemoduleyou 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()