1 引入
当项目中的模块过多,或功能划分不够清晰时会出现循环引用的问题。最近在做毕设,涉及后台管理系统时出现循环引用的问题。
主要copy于:python解决循环引用问题
2 示例
moduleA.py
:
1 2 3 4 5 6 7 8 9 10 11 from moduleB import bdef a () : print('aaaaaaaa' ) b() def c () : print('cccc' ) if __name__ == '__main__' : a()
moduleB.py
:
1 2 3 4 5 from moduleA import cdef b () : print('bbbbbbbbbb' ) c()
运行moduleA.py
出现以下报错:
1 ImportError: cannot import name 'b' from partially initialized module 'moduleB' (most likely due to a circular import)
导入其实是要将 被导入模块所有的代码都执行一遍,遇到函数和类的定义会作申明
。回到循环引用中,首先导入B,进入B中,发现B中又导入了A又回到A中,但是A又导入B这就形成了循环引用。
3 解决
3.1 直接导入模块名,通过模块调用其中的函数
moduleA.py
:
1 2 3 4 5 6 7 8 9 10 11 import moduleBdef a () : print 'aaaaaaaa' moduleB.b() def c () : print 'cccccc' if __name__ == '__main__' : a()
moduleB.py
:
1 2 3 4 5 6 import moduleAdef b () : print 'bbbbbbbbbb' moduleA.c()
3.2 使用延迟导入(lazy import)
在需要用的函数内部导入,或是在底部导入。
moduleA.py
:
1 2 3 4 5 6 7 8 9 10 11 12 from moduleB import bdef a () : print('aaaaaaaa' ) b() def c () : print('cccc' ) if __name__ == '__main__' : a()
moduleB.py
:
1 2 3 4 5 6 7 8 9 10 11 12 13 def b () : print('bbbbbbbbbb' ) c() from moduleA import cdef b () : from moduleA import c print('bbbbbbbbbb' ) c()
3.3 重新设计代码结构,将代码和并或者分离
将公共功能的代码分离成单独模块,或者将一些具有关系的代码合并成一个模块。
本次毕设便采用了这个方法:将一些公共功能的代码分离,config.py (数据库配置)、entity.py (实体类)
config.py
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from sqlalchemy.ext.declarative import declarative_basefrom sqlalchemy import create_engine, Column, Integer, String, TEXTfrom sqlalchemy.orm import sessionmakerHOST = '127.0.0.1' PORT = 3306 USERNAME = 'xxx' PASSWORD = 'xxx' DB = 'xxx' DB_URI = f'mysql+pymysql://{USERNAME} :{PASSWORD} @{HOST} :{PORT} /{DB} ' engine = create_engine(DB_URI) Base = declarative_base(engine) session = sessionmaker(engine)()
entity.py
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 from config import *class Report (Base) : __tablename__ = 'report' id = Column(Integer, primary_key=True , autoincrement=True ) report_name = Column(String(100 )) report_size = Column(String(100 )) source_info = Column(String(100 )) operation = Column(String(100 )) tag = Column(String(100 )) hazard_level = Column(String(100 )) malware_static_info = Column(TEXT()) malware_dynamic_info = Column(TEXT()) upload_time = Column(String(100 )) class MidFid (Base) : __tablename__ = 'malware_mid_fid' id = Column(Integer, primary_key=True , autoincrement=True ) mid = Column(Integer()) fid = Column(Integer())
X 参考
Life is painting a picture, not doing a sum.