python循环导入

比如有如下目录结构:

1
2
3
4
5
6
7
root.py
- A
- __init__.py
- a.py
- B
- __init__.py
- b.py

root.py:

1
from A.a import class_a

a.py:

1
2
3
4
from B.b import class_b

class class_a:
pass

b.py:

1
2
3
4
from A.a import class_a

class class_b:
pass

此时运行 root.py 会发生报错:

ImportError: cannot import name ‘class_a’ from partially initialized module ‘A.a’ (most likely due to a circular import)

我们来解析一下运行过程:

  1. 执行 root.py 的 from A.a import class_a,发现需要导入模块 a
  2. 一个空的字典会被创建,对应 a 的 globals
  3. a.py 中的代码会被执行,当执行到 from B.b import class_b 时,发现需要导入模块 b
  4. 一个空的字典会被创建,对应 b 的 globals
  5. b.py 中的代码会被执行,当执行到 from A.a import class_a 时,发现需要导入模块 a,但此时已经有 a 的 globals 了,所以直接访问字典里的 class_a,但由于 a 的 globals 还是空的,即没有 class_a,所以抛出异常。

总结:循环导入的根本原因就是在导入的时候, b 需要访问 a 的变量 class_a,而 class_a 没有初始化完成。

解决方法:

  1. 在导入的时候,让 b 不要访问 a 的变量
  2. class_a 初始化完成后,才让 b 访问 a 中的变量
方法一

import 整个模块,而不是 import 模块中的变量。

root.py:

1
import A.a

a.py:

1
2
3
4
import B.b

class class_a:
pass

b.py:

1
2
3
4
import A.a

class class_b:
pass

首先编译 a,编译过程中发现需要编译 b,编译 b 完成后,编译 a 剩下的部分。


方法二

把导入放在后面,或者把导入放在语句块中。

root.py:

1
from A.a import class_a

a.py:

1
2
3
4
5
6
7
8
9
10
11
class class_a:
pass

from B.b import class_b
class_b()

# 或者
class class_a:
from B.b import class_b
class_b()

b.py:

1
2
3
4
5
6
7
8
9
10
11
class class_b:
pass

from A.a import class_a
class_a()

# 或者
class class_b:
from A.a import class_a
class_a()