1

可能重复:
Python 中的循环模块依赖项和相对导入

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

主要.py:

from pkg import foo

包/__init.py__:

# empty

包/foo.py:

from pkg import bar

包/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" 和 "from package import module" 是等价的(除了后者中的额外名称绑定)?

4

1 回答 1

2

首先你要明白:

  • sys.modules变量在导入机制中起到缓存的作用,这意味着如果我们第一次导入一个模块,一个包含该模块名称的条目将添加到 中sys.modules,这样当我们下次尝试导入同一个模块时,我们只会从中获取已经缓存的模块sys.modules,我们不会再次执行该模块。

  • import pkg.foo和之间的区别在于from pkg import foo第二个也是等价的:import pkg.foo后跟getattr(pkg, 'foo'). (查看我的答案以获取更多详细信息)

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

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

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

3- In bar.py: 虽然现在导入bar.py我们最终执行 line: from pkg import foo,但请记住我们已经有一个条目,sys.modulespkg.foo意味着执行foo.py将被跳过并且导入机械化将让我们而不是sys.modules['pkg.foo']条目,现在我们将getattr(pkg, 'foo')按照上面的解释执行,但请记住 'pkg.foo' 没有完成导入;这意味着没有属性foo可以解释错误。

现在,如果您bar.py只输入import pkg.foo这个,就不会出现上次导致我们出现问题的行,即:getattr(pkg, 'foo').

高温下,

于 2012-09-08T14:06:11.743 回答