Python 的 __import__ 没有按预期工作

发布于 2024-07-07 02:29:04 字数 143 浏览 8 评论 0原文

当使用带有点名称的 __import__ 时,例如:somepackage.somemodule,返回的模块不是 somemodule,返回的任何内容似乎都是大部分都是空的! 这里发生了什么?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

冷情 2024-07-14 02:29:04

来自 __import__ 上的 python 文档:

__import__( 名称[, 全局变量[, 局部变量[, fromlist[, 级别]]]]) 
  

...

当名称变量的形式为
package.module,通常,
顶级包(名称直到
第一个点)被返回,而不是
按名称命名的模块。 然而,当一个
给出非空 fromlist 参数,
返回按名称命名的模块。
这样做是为了兼容
生成的字节码
不同种类的进口声明;
当使用“导入 spam.ham.eggs”时,
必须放置顶级垃圾邮件包
在导入命名空间中,但是当
使用“从 spam.ham 导入鸡蛋”,
必须使用 spam.ham 子包
找到鸡蛋变量。 作为一个
此行为的解决方法,使用
getattr() 提取所需的
成分。 例如,您可以
定义以下助手:

def my_import(名称): 
      mod = __import__(名称) 
      组件 = name.split('.') 
      对于组件 [1:] 中的 comp: 
          mod = getattr(mod, comp) 
      返回模式 
  

解释一下:

当您请求 somepackage.somemodule 时,__import__ 返回 somepackage.__init__.py >,通常是空的。

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

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

注:我问这个问题完全是为了自己回答。 我的代码中有一个大错误,并且误诊了它,我花了很长时间才弄清楚,所以我想我应该帮助 SO 社区解决这个问题,并将我遇到的问题发布在这里。

From the python docs on __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

To paraphrase:

When you ask for somepackage.somemodule, __import__ returns somepackage.__init__.py, which is often empty.

It will return somemodule if you provide fromlist (a list of the variable names inside somemodule you want, which are not actually returned)

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.

放赐 2024-07-14 02:29:04

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

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

python 2.7 has importlib, dotted paths resolve as expected

import importlib
foo = importlib.import_module('a.dotted.path')
instance = foo.SomeClass()
夜清冷一曲。 2024-07-14 02:29:04

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

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

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

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
>>> name = 'foo.bar.baz'
>>> __import__(name)
<module 'foo' from ...>
>>> baz = sys.modules[name]
>>> baz
<module 'foo.bar.baz' from ...>
酒几许 2024-07-14 02:29:04

有一些东西可以按照您想要的方式工作: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'>

There is something that works as you want it to: 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'>
不寐倦长更 2024-07-14 02:29:04

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

For python 2.6, I wrote this snippet:

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
旧城空念 2024-07-14 02:29:04

我所做的方式是

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

然后我可以访问任何内容

foobar.functionName()

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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文