5

Python 实战项目解决循环依赖问题

 2 years ago
source link: https://blog.frytea.com/archives/610/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Python 实战项目解决循环依赖问题

December 27, 2021 • Read: 79 • 编程开发

本文首发于: https://blog.frytea.com/archives/610/

在一次简单的代码合并后,发现 Python 项目跑不起来了,报错如下:

ssh://[email protected]:22/usr/bin/python3 -B -u /tmp/pycharm_project_882/mimic_daemon_server/helper_main.py
Traceback (most recent call last):
File "/tmp/pycharm_project_882/mimic_daemon_server/helper_main.py", line 1, in <module>
from mimic_daemon_server import create_app
File "/tmp/pycharm_project_882/mimic_daemon_server/__init__.py", line 14, in <module>
from mimic_daemon_server.nodes import nodes
File "/tmp/pycharm_project_882/mimic_daemon_server/nodes/__init__.py", line 2, in <module>
from . import route
File "/tmp/pycharm_project_882/mimic_daemon_server/nodes/route.py", line 5, in <module>
from mimic_daemon_server.guest_common import ReplicationConfig
File "/tmp/pycharm_project_882/mimic_daemon_server/guest_common/__init__.py", line 3, in <module>
from .abstract_config import AbstractConfig
File "/tmp/pycharm_project_882/mimic_daemon_server/guest_common/abstract_config.py", line 16, in <module>
import mimic_daemon_server.qemu_server.Drive
File "/tmp/pycharm_project_882/mimic_daemon_server/qemu_server/__init__.py", line 25, in <module>
from .QemuConfig import QemuConfig
File "/tmp/pycharm_project_882/mimic_daemon_server/qemu_server/QemuConfig.py", line 12, in <module>
from mimic_daemon_server.guest_common import AbstractConfig
ImportError: cannot import name 'AbstractConfig' from 'mimic_daemon_server.guest_common' (/tmp/pycharm_project_882/mimic_daemon_server/guest_common/__init__.py)
进程已结束,退出代码1

由于我在 Python 领域还是个初学者,没有遇到类似问题,但是根据分析,问题应该是出在了 循环依赖

a------->b-------->c
+----d<---+

何为循环依赖呢?首先要搞清楚一点,python 模块是天然的单例类,就是说第一次导入时会产生一个实例,后面再导入都会直接返回该实例。

模块的初始化时被导入时进行的,就是说每一次 import 都会执行 __init__.py 内的代码。

一旦 Python 的模块导入规划不合理,造成了多个互相依赖的模块均在第一次进入时开始实例化,就会产生 循环依赖 问题。

总结一下,Python 模块是可以循环依赖的,但是必须避免循环实例化

解决循环依赖的方法也有很多:

(1) 打破循环实例化态

如果想快速解决,在报错日志中找到循环实例化的两个模块,打破其循环实例化的状态即可。

例如观察文首的一段日志,会很明显的发现调用栈中前后引入了同一个模块,很容易定位到问题。

(2) 强制指定实例化顺序

可以在整个项目的根模块中的 __init__.py 中将所有子模块依赖一遍,调整可能出现循环依赖的顺序,就可以避免后期模块间依赖时产生不可预知的循环依赖问题。

也可以在模块中提供一个 init 方法,在需要的地方手动控制实例化顺序,避免导入时意外的循环依赖。

Python 模块间可以随意引用,但是必须注意实例化的前后顺序,否则就会出现这种循环实例化问题,让人摸不着头脑。

---------------------
Author: Frytea
Title: Python 实战项目解决循环依赖问题
Link: https://blog.frytea.com/archives/610/
Copyright: This work by TL-Song is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK