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



可能重复:
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 

将使该示例起作用。

为什么会发生这种情况?*import-package.module"one_answers"from package import-module"不应该等效吗(除了后者中的额外名称绑定)?

首先你必须明白:

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

  • import pkg.foofrom pkg import foo的区别在于,第二个也是等效的:import pkg.foo后面跟着getattr(pkg, 'foo')。(查看我的答案以了解更多详细信息)

现在,在您的第一个示例中发生的情况如下:

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

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

3-在bar.py中:当现在导入bar.py时,我们最终执行的行是:from pkg import foo,但请记住,我们在sys.modules中已经有一个pkg.foo的条目,这意味着执行foo.py将被跳过,而导入mechanize将为我们获取sys.modules['pkg.foo']条目,现在我们将如上所述执行getattr(pkg, 'foo'),但请记得"pkg.foo"没有完成导入;这意味着不存在解释该错误的属性CCD_ 31。

现在,如果你只放入bar.py中的import pkg.foo,这将不会有上次导致我们出现问题的行,即:getattr(pkg, 'foo')

HTH、

最新更新