使用包导入模块语法时,Python循环导入失败

时间:2012-09-08 12:56:19

标签: python import cyclic-reference

  

可能重复:
  Cyclic module dependencies and relative imports in Python

在python中考虑下面的循环导入示例:

main.py:

from pkg import foo

PKG / __ init.py __:

# empty

PKG / foo.py:

from pkg import bar

PKG / bar.py:

from pkg import foo

运行main.py会导致异常:

Traceback (most recent call last):
  File "/path/to/main.py", line 1, in <module>
    from pkg import foo
  File "/path/to/pkg/foo.py", line 1, in <module>
    from pkg import bar
  File "/path/to/pkg/bar.py", line 1, in <module>
    from pkg import foo
ImportError: cannot import name foo

将bar.py更改为:

# from pkg import foo
import pkg.foo 

将使示例有效。

为什么会这样?不应该*导入package.module“和”从包导入模块“是等效的(除了后者中的额外名称绑定)?

1 个答案:

答案 0 :(得分:2)

首先你必须明白:

  • sys.modules变量在导入机制中扮演缓存的角色,这意味着如果我们第一次导入模块,则会将包含此模块名称的条目添加到{{1}因此,当我们下次尝试导入同一个模块时,我们只会从sys.modules获取已缓存的模块,我们将不再执行该模块。

  • sys.modulesimport pkg.foo之间的区别在于第二个也是等效的:from pkg import foo后跟import pkg.foo。 (查看我的回答here了解更多详情)

现在你的第一个例子中发生了以下情况:

1-在getattr(pkg, 'foo')中:我们首先执行第main.py行,因此首先将条目from pkg import foo添加到pkg.foo(即sys.modules)我们尝试导入'pkg.foo' in sys.modules == True

2-在foo中:导入foo.py时,我们最终执行此行:foo并再次将条目from pkg import bar添加到pkg.bar;而且我们开始导入sys.modules,这里需要注意的是我们仍在执行bar,所以我们仍然可以从foo.py执行此行from pkg import foo

3-在main.py中:在导入bar.py时,我们最终会执行以下行:bar.py,但请记住我们from pkg import foo中已有sys.modules的条目这意味着将跳过执行pkg.foo,导入机制将使我们获得foo.py条目,现在我们将执行sys.modules['pkg.foo'],如上所述,但请记住'pkg.foo '没有完成进口;这意味着没有解释错误的属性getattr(pkg, 'foo')

现在,如果您只使用foo bar.py,那么上次不会出现导致我们问题的行:import pkg.foo

HTH,