python重复import_Python 中循环 import 造成的问题如何解决?
使用python寫一個稍微大一點的工程時,經常會遇到循環import,即cicular import的問題。我以flask里遇到的一個問題為原型,介紹一下 circular 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
from app import app
File "/Users/caoxin/work/python_project/flask_demo/app/__init__.py", line 24, in
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
from app import login_manager
ImportError: cannot import name 'login_manager' from 'app' (/Users/caoxin/work/python_project/flask_demo/app/__init__.py)
這是一個典型的circular 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的問題便很好分析和解決了。
總結
以上是生活随笔為你收集整理的python重复import_Python 中循环 import 造成的问题如何解决?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Drupal迁移 | 如何创建一个Dru
- 下一篇: c# chart 各个属性_c# Cha