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

使用“从包导入”模块语法时,Python循环导入失败,python,import,cyclic-reference,Python,Import,Cyclic Reference,可能重复: 考虑以下python中循环导入的示例: main.py: from pkg import foo pkg/\uuuu init.py\uuuu: # empty pkg/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 <mo

可能重复:

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

main.py:

from pkg import foo
pkg/\uuuu init.py\uuuu:

# empty
pkg/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
这将使这个例子起作用


为什么会发生这种情况?*import package.module“和”from package import module“不应该是等价的吗(后面的额外名称绑定除外)?

首先,您必须了解:

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

  • import-pkg.foo
    和pkg-import-foo中的
    之间的区别在于,第二个也是等效的:
    import-pkg.foo
    后跟
    getattr(pkg,'foo')
    (查看我的答案了解更多细节)

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

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

2-在
foo.py
:当导入
foo
时,我们最终执行这一行:
从pkg导入bar
,然后再次将条目
pkg.bar
添加到
sys.modules
;然后开始导入
bar
,这里需要注意的是,我们仍然在执行
foo.py
,所以我们很友好off仍然从pkg import foo执行这一行

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

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


HTH,

我已经用python 2.7.3进行了测试。python 3.2.3也有同样的表现。可能会对你有所帮助。特别是第二个答案。或者更好的答案。谢谢@Bakariu。链接给出了我问题的确切答案。我已经在评论中链接了你的答案,并将这个问题标记为重复,因为问题实际上是相同的。谢谢@mouad.我不可能要求更好的答案。我的理由是(如果我没有弄错的话)使用
getattr(pkg,'foo')
代替
sys.modules['pkg.foo']
,因为当
x
是一个模块而
y
是模块
x
中的一个字段时,同样的
语法必须工作。
# from pkg import foo
import pkg.foo