好的,我确实理解这个话题已经过时了,但我找不到我要问的特定问题的答案。
假设我们的结构非常简单:两个文件a.py
和b.py
,其内容为:
a.py
import b
class C:
lal = 4
class A:
kek = 12
lol = b.B()
b.py
import a
class B:
aa = a.C()
尝试运行python b.py
,我们得到:
Traceback (most recent call last):
File "b.py", line 1, in <module>
import a
File ".../a.py", line 1, in <module>
import b
File ".../b.py", line 3, in <module>
class B:
File ".../a.py", line 5, in A
aa = a.C()
AttributeError: module 'a' has no attribute 'C'
但是如果我们移动import b
行 AFTER C
类,则脚本会启动并且不会产生任何错误。
我在SO上的任何答案中都没有提到任何这方面的内容。这里的问题是:为什么会发生这种情况, 如何 来逃避这种情况?
对于Django框架来说,这是一个特别重要的问题。当我有很多模型时,我会尝试将它们分成许多文件。在那里进行循环导入非常容易。
答案 0 :(得分:1)
在python中导入模块时,它首先导入在模块顶部定义的所有模块,如果模块不在sys.modules中,则导入会在sys.modules中创建新模块条目然后执行模块中的代码。
因此,当您尝试在a.py中导入b.py模块时,如果模块未在sys.modules中列出,则首先导入b.py中列出的所有模块为a.py(导入a)。仍然没有完全执行模块b.py所以b.py模块没有添加到sys.modules
之后,它尝试导入a.py并在a.py中尝试首先导入所有在a.py中导入的模块是b.py
所以这是一个基本周期a.py尝试导入b.py和b.py尝试导入a.py
对于该问题,解决方案是在类中导入一个模块或类,而不是在模块的顶部
根据你的例子
<强> a.py 强>
class C:
lal = 4
class A:
import b
kek = 12
lol = b.B()
<强> b.py 强>
import a
class B:
aa = a.C()
或
<强> a.py 强>
import b
class C:
lal = 4
class A:
kek = 12
lol = b.B()
<强> b.py 强>
class B:
import a
aa = a.C()
答案 1 :(得分:0)
实际上@Kallz已经提供了正确的答案,但你有点顽固:)你正在创建循环引用,它将以无限循环结束。 Python有一个机制,可以逐行逐行避免这种循环。首先打开b.py - 它作为'__main__'加载到sys.modules中并开始加载。加载它时会出现'import a'。所以它寻找模块'a'。它找到它并将其放入sys.modules中。 sys.modules现在有'__main__'和'a'。它开始加载模块'a',遇到'import b'。所以它找到'b.py'并将其放入sys.modules中。现在你有'__main__','a','b',它开始加载'b',遇到'import a' - 这次模块'a'已经在sys.modules中了,加载它已经开始了!所以Python知道正在发生的事情,你自己就是一个ImportError。