在Python中,当两个模块试图相互导入时会发生什么?更一般地说,如果多个模块试图在一个循环中导入会发生什么?
另见我能做什么关于“ImportError:不能导入名称X”或“AttributeError:…”(很可能是由于循环导入)”?关于可能导致的常见问题,以及如何重写代码以避免此类导入的建议。参见为什么循环导入看起来在调用堆栈中更上一层,但随后在更下一层引发ImportError ?有关问题发生的原因和方式的技术细节。
在Python中,当两个模块试图相互导入时会发生什么?更一般地说,如果多个模块试图在一个循环中导入会发生什么?
另见我能做什么关于“ImportError:不能导入名称X”或“AttributeError:…”(很可能是由于循环导入)”?关于可能导致的常见问题,以及如何重写代码以避免此类导入的建议。参见为什么循环导入看起来在调用堆栈中更上一层,但随后在更下一层引发ImportError ?有关问题发生的原因和方式的技术细节。
当前回答
我用下面的方法解决了这个问题,没有任何错误。 考虑两个文件a.py和b.py。
我把这个添加到a.py,它工作了。
if __name__ == "__main__":
main ()
a.py:
import b
y = 2
def main():
print ("a out")
print (b.x)
if __name__ == "__main__":
main ()
b.py:
import a
print ("b out")
x = 3 + a.y
得到的输出是
>>> b out
>>> a out
>>> 5
其他回答
这里有个例子让我震惊!
foo.py
import bar
class gX(object):
g = 10
bar.py
from foo import gX
o = gX()
main.py
import foo
import bar
print "all done"
在命令行:$ python main.py
Traceback (most recent call last):
File "m.py", line 1, in <module>
import foo
File "/home/xolve/foo.py", line 1, in <module>
import bar
File "/home/xolve/bar.py", line 1, in <module>
from foo import gX
ImportError: cannot import name gX
去年在comp.lang.python上对此进行了很好的讨论。它很彻底地回答了你的问题。
Imports are pretty straightforward really. Just remember the following: 'import' and 'from xxx import yyy' are executable statements. They execute when the running program reaches that line. If a module is not in sys.modules, then an import creates the new module entry in sys.modules and then executes the code in the module. It does not return control to the calling module until the execution has completed. If a module does exist in sys.modules then an import simply returns that module whether or not it has completed executing. That is the reason why cyclic imports may return modules which appear to be partly empty. Finally, the executing script runs in a module named __main__, importing the script under its own name will create a new module unrelated to __main__. Take that lot together and you shouldn't get any surprises when importing modules.
我完全同意pythoneer的回答。但是我偶然发现了一些代码,它们在循环导入时存在缺陷,并在尝试添加单元测试时引起了问题。因此,为了快速修补它而不改变一切,你可以通过动态导入来解决这个问题。
# Hack to import something without circular import issue
def load_module(name):
"""Load module using imp.find_module"""
names = name.split(".")
path = None
for name in names:
f, path, info = imp.find_module(name, path)
path = [path]
return imp.load_module(name, f, path[0], info)
constants = load_module("app.constants")
同样,这不是一个永久性的修复,但可以帮助那些希望在不修改太多代码的情况下修复导入错误的人。
干杯!
假设您正在运行一个名为request.py的测试python文件 在request.py中,您写入
import request
所以这也很可能是一个循环导入。
解决方案:
只需将测试文件更改为另一个名称,例如aaa.py,而不是request.py。
不要使用其他库已经使用过的名称。
正如其他答案所描述的,这种模式在python中是可以接受的:
def dostuff(self):
from foo import bar
...
这将避免在文件被其他模块导入时执行import语句。只有当存在逻辑循环依赖时,这才会失败。
大多数循环导入实际上不是逻辑循环导入,而是会引发ImportError错误,这是因为import()在调用时计算整个文件的顶级语句的方式。
如果你确实想要你的导入在顶部,这些ImportErrors几乎总是可以避免的:
考虑这个循环导入:
应用一个
# profiles/serializers.py
from images.serializers import SimplifiedImageSerializer
class SimplifiedProfileSerializer(serializers.Serializer):
name = serializers.CharField()
class ProfileSerializer(SimplifiedProfileSerializer):
recent_images = SimplifiedImageSerializer(many=True)
应用程序B
# images/serializers.py
from profiles.serializers import SimplifiedProfileSerializer
class SimplifiedImageSerializer(serializers.Serializer):
title = serializers.CharField()
class ImageSerializer(SimplifiedImageSerializer):
profile = SimplifiedProfileSerializer()
来自David Beazleys的精彩演讲:模块和包:生存和死亡!PyCon 2015, 1:54:00,这里是一个处理python循环导入的方法:
try:
from images.serializers import SimplifiedImageSerializer
except ImportError:
import sys
SimplifiedImageSerializer = sys.modules[__package__ + '.SimplifiedImageSerializer']
它尝试导入SimplifiedImageSerializer,如果ImportError被引发,因为它已经被导入,它将从importcache中拉出它。
PS:你必须用David Beazley的声音来阅读整篇文章。