python 报错 most likely due to a circular import 解决方法

原因各个python文件,互相引用,造成的 循环引用问题。

解决方法:把需要引用的独立成一个文件,让其单向引用

使用python写一个稍微大一点的工程时,经常会遇到循环import,即cicular import的问题。这篇文章会以flask里遇到的一个问题为原型,介绍一下
cicular import产生的原因,以及python中使用import文件时,到底python在做什么。

1. 一个circular import实例

之前遇到一个circular import的问题,项目文件结构大概如下:

flask_demo\
  app\
    auth\
      __init__.py
    __init__.py
  run_server.py

app目录下__init__.py文件内容如下:

from flask import Flask
from flask_login import LoginManager

def create_app():
    app = Flask(__name__)

    from app.auth import auth_bp
    app.register_blueprint(auth_bp)

    return app
    
app = create_app()
login_manager = LoginManager(app)

app/auth目录下__init__.py文件内容如下:

from flask import Blueprint
from app import login_manager

# 注册蓝图
auth_bp = Blueprint('auth_bp', __name__)

最后运行run_server.py文件:

from app import app

app.run()

这个时候flask web应用并不会成功启动起来,而是会报下面的错误:

Traceback (most recent call last):
  File "/Users/caoxin/work/python_project/flask_demo/run_server.py", line 10, in <module>
    from app import app
  File "/Users/caoxin/work/python_project/flask_demo/app/__init__.py", line 24, in <module>
    app = create_app()
  File "/Users/caoxin/work/python_project/flask_demo/app/__init__.py", line 17, in create_app
    from app.auth import auth_bp
  File "/Users/caoxin/work/python_project/flask_demo/app/auth/__init__.py", line 11, in <module>
    from app import login_manager
ImportError: cannot import name 'login_manager' from 'app' (/Users/caoxin/work/python_project/flask_demo/app/__init__.py)

这是一个典型的cicular import问题,要解决这个问题,需要能够很好的理解,在python中使用import时,代码到底是如何运行的。

2. import执行过程

当我们import一个文件时,python会首先去查找这个文件之前是否被import过,如果这个文件之前有被import过,就不会重新再import一次。所以如果A模块
代码里import了B模块,并且B模块里又import了A模块,python的执行顺序会变成这样:

  • 开始执行模块A
  • 当A执行到import B的地方,则停止执行A模块后面的代码,转而开始执行B模块的代码
  • 当B模块从头执行到import A的地方时,python此时并不会回过头去接着执行A剩余的代码,而且将A模块在中断前已经初始化的属性全加载到B模块中

我们以上面的例子来分件,app/init.py中create_app()方法中的from auth import auth_bp会中断app/init.py的执行,转而去执行
auth/init.py。需要注意的是,此时app/init.py里的app和login_manager两个属性都是声明的。而auth/init.py又想从app模块里导入
login_manager这个属性。很显然,这里就会报错。要解决这个问题,我们就需要重新设计代码结构,保证在auth/init.py在执行到from app import
login_manager时,app模块中已经定义了login_manager。如下:

from flask import Flask
from flask_login import LoginManager

login_manager = LoginManager() # 在auth模块运行之前,先声明login_manager

def create_app():
    app = Flask(__name__)
    login_manager.init_app(app)

    from app.auth import auth_bp
    app.register_blueprint(auth_bp)

    return app

app = create_app()

所以理解了python在import时的工作原理,这种circular import的问题便很好分析和解决了。

  • 29
    点赞
  • 85
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
很可能是由于循环导入引起的。循环导入是指两个或多个模块相互引用,导致无法正确加载模块的情况。当一个模块试图导入另一个模块时,如果被导入的模块又试图导入第一个模块,就会出现循环导入的问题。这种情况下,Python解释器无法确定模块的加载顺序,从而导致ImportError。解决循环导入问题的方法有多种,可以通过重构代码,将导入语句放在函数内部,或者使用延迟导入等方式来避免循环导入的发生。\[2\]\[3\] #### 引用[.reference_title] - *1* [Python 进行debug的错误most likely due to a circular import](https://blog.csdn.net/domyself918/article/details/123379364)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [python 报错 most likely due to a circular import 解决方法](https://blog.csdn.net/whatday/article/details/109333877)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [【ModuleNotFoundError 与 ImportError】之 most likely due to a circular import](https://blog.csdn.net/fancunshuai/article/details/125103676)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值