Flask中的循環(huán)導(dǎo)入

問(wèn)題

Flask中的app實(shí)例是一個(gè)很重要的單例,當(dāng)我們?cè)谧鲆晥D函數(shù)拆分的時(shí)候,如果不做考慮,很容易造成循環(huán)引入的問(wèn)題。

比如說(shuō)我們?cè)趯慺lask應(yīng)用的時(shí)候,要把a(bǔ)pp.py中的視圖函數(shù)提取到另一個(gè)py文件,而在視圖函數(shù)中注冊(cè)路由時(shí)需要app的實(shí)例,因此就會(huì)導(dǎo)入app.py中的app實(shí)例,而為了能夠完成路由的注冊(cè),app.py 需要導(dǎo)入視圖函數(shù)的模塊,這個(gè)時(shí)候就形成了一個(gè)循環(huán)引用。

# app.py
from flask import Flask

app = Flask(__name__) # 實(shí)例化一個(gè)Flask對(duì)象

import admin # 這里導(dǎo)入admin是為了完成admin.py中路由的注冊(cè)

if __name__ == '__main__':
    app.run()
# admin.py
from app import app # 為了注冊(cè)路由,需要導(dǎo)入app.py中的app實(shí)例

@app.route('/admin')  
def index():
    return 'hello world!'

這時(shí)候如果運(yùn)行app.py發(fā)現(xiàn)什么錯(cuò)誤都不會(huì)報(bào),但是訪問(wèn)/admin時(shí)候,會(huì)發(fā)現(xiàn)404錯(cuò)誤,找不到路由。
為什么會(huì)這樣呢。

代碼分析

輸出 app 實(shí)例的 id 來(lái)看一下就明白了。

# app.py
from flask import Flask

app = Flask(__name__) # 實(shí)例化一個(gè)Flask對(duì)象
print('id為{}的app實(shí)例化'.format(id(app)))
import admin # 這里導(dǎo)入admin是為了完成admin.py中路由的注冊(cè)

if __name__ == '__main__':
    print('id為{}的app啟動(dòng)'.format(id(app)))
    app.run()
# admin.py
from run import app

print('id為{}的app注冊(cè)路由'.format(id(app)))


@app.route('/admin')
def index():
    return 'hello world'

運(yùn)行一下,結(jié)果如下:

id為2052896477592的app實(shí)例化
id為2050881952288的app實(shí)例化
id為2050881952288的app注冊(cè)路由
id為2052896477592的app啟動(dòng)
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

可以看到 app 被實(shí)例化了兩次,而且注冊(cè)路由的 app 和最終啟動(dòng)的 app 不是同一個(gè) app 實(shí)例,所以會(huì)出現(xiàn)404。
為什么會(huì)執(zhí)行兩次呢。下面用圖表示一下運(yùn)行過(guò)程。

流程圖分析


首先程序從app.py中運(yùn)行,執(zhí)行到import admin 時(shí),會(huì)進(jìn)入admin文件,當(dāng)在admin文件中再次調(diào)用app時(shí),又返回到app.py文件中運(yùn)行,但是python不會(huì)重復(fù)循環(huán)導(dǎo)入,所以第二次的時(shí)候就不會(huì)再次進(jìn)入admin文件中,便向下執(zhí)行if語(yǔ)句,此時(shí)的app.py文件是被admin.py文件調(diào)用的,所以此時(shí)的__name__ != __main__,所以不會(huì)運(yùn)行app.run()方法,執(zhí)行完app.py文件時(shí),便會(huì)回到admin中繼續(xù)執(zhí)行app route,調(diào)用完成后回到app中,繼續(xù)執(zhí)行,此時(shí)的app實(shí)例才是app.py中的,所以會(huì)執(zhí)行run。

解決方法

解決循環(huán)導(dǎo)入的方法有很多種方式,在Flask中通常使用藍(lán)圖來(lái)實(shí)現(xiàn)模塊化,解決循環(huán)導(dǎo)入的問(wèn)題。
藍(lán)圖的使用

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容