第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

Flask 的鉤子函數(shù)使用

Flask 框架提供了鉤子函數(shù)的機(jī)制用于在特定的位置執(zhí)行用戶(hù)注冊(cè)的函數(shù),本小節(jié)講解了常見(jiàn)的鉤子函數(shù)的使用。

1. 鉤子簡(jiǎn)介

1.1 什么是鉤子

在服務(wù)端處理請(qǐng)求時(shí),有時(shí)需要:在處理請(qǐng)求前執(zhí)行一些準(zhǔn)備工作,在處理請(qǐng)求后執(zhí)行一些掃尾工作,例如:

@app.route('/page1')
def page1():
    執(zhí)行準(zhǔn)備工作
    執(zhí)行請(qǐng)求
    執(zhí)行掃尾工作

@app.route('/page2')
def page2():
    執(zhí)行準(zhǔn)備工作
    執(zhí)行請(qǐng)求
    執(zhí)行掃尾工作

程序包括有 2 個(gè)頁(yè)面:page1 和 page2,在每個(gè)頁(yè)面處理函數(shù)的頭部,執(zhí)行準(zhǔn)備工作;在每個(gè)頁(yè)面處理函數(shù)的尾部,執(zhí)行掃尾工作。

以上程序存在的明顯的代碼重復(fù)問(wèn)題,為了讓每個(gè)頁(yè)面處理函數(shù)避免編寫(xiě)重復(fù)功能的代碼,F(xiàn)lask 提供了鉤子函數(shù)機(jī)制:Flask 給應(yīng)用程序提供掛載點(diǎn),在掛載點(diǎn)調(diào)用應(yīng)用程序注冊(cè)的函數(shù),該函數(shù)被稱(chēng)為鉤子函數(shù)。

1.2 注冊(cè)鉤子

Flask 框架處理請(qǐng)求時(shí),提供了 2 個(gè)掛載點(diǎn):before_request 和 after_request,執(zhí)行請(qǐng)求的流程如下:

  1. 執(zhí)行在掛載點(diǎn) before_request 注冊(cè)的鉤子函數(shù);
  2. 執(zhí)行頁(yè)面處理函數(shù);
  3. 執(zhí)行在掛載點(diǎn) after_request 注冊(cè)的鉤子函數(shù)。

Flask 使用裝飾器的語(yǔ)法注冊(cè)鉤子函數(shù),如下所示:

@app.before_request
def before_request():
    print('before request')

使用裝飾器 @app.before_request 在掛載點(diǎn) before_request 注冊(cè)函數(shù) before_request,F(xiàn)lask 在處理每個(gè)請(qǐng)求時(shí):

  • 首先調(diào)用函數(shù) before_request,打印字符串 ‘before request’;
  • 然后再執(zhí)行請(qǐng)求的處理函數(shù)。

1.3 消除代碼重復(fù)

下面使用鉤子函數(shù)機(jī)制消除 1.1 小節(jié)的代碼重復(fù):

@app.before_request
def before_request():
    執(zhí)行準(zhǔn)備工作

@app.after_request
def after_request():
    執(zhí)行掃尾工作

@app.route('/page1')
def page1():
    執(zhí)行請(qǐng)求

@app.route('/page2')
def page2():
    執(zhí)行請(qǐng)求

在第 1 行,在掛載點(diǎn) before_request 注冊(cè)處理函數(shù),執(zhí)行請(qǐng)求前會(huì)調(diào)用該函數(shù)執(zhí)行準(zhǔn)備工作;在第 5 行,在掛載點(diǎn) after_request 注冊(cè)處理函數(shù),執(zhí)行請(qǐng)求前后調(diào)用該函數(shù)執(zhí)行掃尾工作。

與 1.1 小節(jié)中的代碼相比,頁(yè)面 /page1 和頁(yè)面 /page2 的處理函數(shù)得到了簡(jiǎn)化,準(zhǔn)備工作和掃尾工作被統(tǒng)一放置在鉤子函數(shù)中進(jìn)行。

2. 常用的鉤子

Flask 框架中常用的鉤子總結(jié)如下:

1. before_first_request
在應(yīng)用程序?qū)嵗牡谝粋€(gè)請(qǐng)求之前要運(yùn)行的函數(shù),只會(huì)運(yùn)行一次。

2. before_request
在每個(gè)請(qǐng)求之前要運(yùn)行的函數(shù),對(duì)每一次請(qǐng)求都會(huì)執(zhí)行一次。

3. after_request
在每個(gè)請(qǐng)求之后要運(yùn)行的函數(shù),對(duì)每一次請(qǐng)求都會(huì)執(zhí)行一次。

在 after_request 注冊(cè)的鉤子函數(shù)的第一個(gè)參數(shù)是 response 對(duì)象。

4. teardown_request
在每個(gè)請(qǐng)求之后要運(yùn)行的函數(shù),對(duì)每一次請(qǐng)求都會(huì)執(zhí)行一次。

在 teardown_request 注冊(cè)的鉤子函數(shù)的第一個(gè)參數(shù)是 exception 對(duì)象,指向執(zhí)行請(qǐng)求時(shí)發(fā)生的錯(cuò)誤。

5. errorhandler
發(fā)生一些異常時(shí),比如 HTTP 404、HTTP 500 錯(cuò)誤,或者拋出異常,就會(huì)自動(dòng)調(diào)用該鉤子函數(shù)。

3. 鉤子的基本使用

3.1 程序代碼 basis.py

編寫(xiě)一個(gè)程序 basis.py 分別在處理請(qǐng)求前、處理請(qǐng)求后注冊(cè)鉤子函數(shù):

from flask import Flask, request, render_template

app = Flask(__name__)

@app.route('/')
def index():
    print('execute request')
    return 'Hello World'

@app.before_first_request
def before_first_request():
    print('before_first_request')

@app.before_request
def before_request():
    print('before_request')

@app.after_request
def after_request(response):
    print('after_request')
    return response

if __name__ == '__main__':
    app.run()

在第 10 行,通過(guò) @app.before_first_request 注冊(cè)在第一次處理請(qǐng)求時(shí)執(zhí)行的鉤子函數(shù),該函數(shù)打印字符串 ‘before_first_request’。

在第 14 行,通過(guò) @app.before_request 注冊(cè)在每次處理請(qǐng)求前執(zhí)行的鉤子函數(shù),該函數(shù)打印字符串 ‘before_request’。

在第 18 行,通過(guò) @app.after_request 注冊(cè)在每次處理請(qǐng)求后執(zhí)行的鉤子函數(shù),該函數(shù)打印字符串 ‘a(chǎn)fter_request’。鉤子函數(shù) after_request(response) 的輸入?yún)?shù)是一個(gè) Response 對(duì)象,函數(shù)返回的也是一個(gè) Response 對(duì)象。

3.2 運(yùn)行程序 basis.py

1. 啟動(dòng)程序

$ python basis.py

2. 在瀏覽器中首次訪(fǎng)問(wèn) http://localhost:5000

3. 觀察控制臺(tái)的輸出

before_first_request
before_request
execute request
after_request

應(yīng)用程序在第一個(gè)請(qǐng)求之前要運(yùn)行一次 before_first_request,只會(huì)運(yùn)行一次。

4. 在瀏覽器中再次訪(fǎng)問(wèn) http://localhost:5000

5. 觀察控制臺(tái)的輸出

before_request
execute request
after_request

在程序整個(gè)生命周期內(nèi),before_first_request,只會(huì)運(yùn)行一次,因此再次訪(fǎng)問(wèn)網(wǎng)站時(shí),不會(huì)再執(zhí)行 before_first_request。

4. after_request 與 teardown_request 的區(qū)別

4.1 程序代碼 diff.py

本節(jié)通過(guò)一個(gè)具體的例子講解 after_request 與 teardown_request 的區(qū)別,代碼如下:

from flask import Flask, request, render_template

app = Flask(__name__)

@app.route('/')
def index():
    print('execute request without error')
    return 'Hello World'

@app.route('/error')
def error():
    print('execute request with error')
    1 / 0
    return 'Hello World'

@app.after_request
def after_request(response):
    print('after_request')
    return response

@app.teardown_request
def teardown_request(exception):
    print('teardown_request:', exception)

if __name__ == '__main__':
    app.run()

在第 5 行,訪(fǎng)問(wèn)頁(yè)面 / 時(shí)執(zhí)行函數(shù) index(),該函數(shù)打印字符串 ‘execute request without error’,執(zhí)行期間沒(méi)有發(fā)生異常。

在第 10 行,訪(fǎng)問(wèn)頁(yè)面 /error 時(shí)執(zhí)行函數(shù) error(),該函數(shù)打印字符串 ‘execute request with error’,執(zhí)行期間發(fā)生異常。在第 13 行,人為的通過(guò) 1 / 0 引發(fā)除零異常。

在第 16 行,注冊(cè) after_request 鉤子函數(shù),執(zhí)行請(qǐng)求后會(huì)調(diào)用該鉤子函數(shù)。

在第 21 行,注冊(cè) teardown_request 鉤子函數(shù),執(zhí)行請(qǐng)求后都會(huì)調(diào)用該鉤子函數(shù)。鉤子函數(shù)的第一個(gè)參數(shù)是 exception 對(duì)象,指向執(zhí)行請(qǐng)求時(shí)發(fā)生的錯(cuò)誤。

4.2 運(yùn)行程序 diff.py

1. 啟動(dòng)程序 diff.py

$ python diff.py

2. 在瀏覽器中訪(fǎng)問(wèn) http://localhost:5000

3. 觀察控制臺(tái)的輸出

execute request without error
after_request
teardown_request: None

訪(fǎng)問(wèn)頁(yè)面 / 時(shí),執(zhí)行處理函數(shù) index,執(zhí)行請(qǐng)求結(jié)束后,會(huì)調(diào)用 after_request 和 teardown_request。該函數(shù)執(zhí)行期間沒(méi)有發(fā)生異常,傳遞給 teardown_request 鉤子函數(shù)的 exception 對(duì)象為 None。

4. 在瀏覽器中訪(fǎng)問(wèn) http://localhost:5000/error

5. 觀察控制臺(tái)的輸出

execute request with error
Traceback (most recent call last):
  File "diff.py", line 14, in error
    1 / 0
ZeroDivisionError: division by zero
after_request
teardown_request: division by zero

訪(fǎng)問(wèn)頁(yè)面 /error 時(shí),執(zhí)行處理函數(shù) error,執(zhí)行請(qǐng)求結(jié)束后,會(huì)調(diào)用 after_request 和 teardown_request。該函數(shù)執(zhí)行期間發(fā)生異常,傳遞給 teardown_request 鉤子函數(shù)的 exception 對(duì)象為 ZeroDivisionError。

5. 錯(cuò)誤處理

5.1 程序代碼 error.py

通過(guò)一個(gè)具體的例子講解使用 errorhandler 處理 HTTP 錯(cuò)誤,代碼如下:

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
    print('execute request')
    return 'Hello World'

@app.errorhandler(404)
def errorhandler(e):
    print('error_handler(404)')
    print(e)
    return '404 Error'

if __name__ == '__main__':
    app.run()

在第 10 行,使用 @errorhandler(404) 注冊(cè)一個(gè)鉤子函數(shù) errorhandler(e),當(dāng)發(fā)生 HTTP 404 錯(cuò)誤(頁(yè)面不存在)時(shí),調(diào)用鉤子函數(shù),該函數(shù)的第一個(gè)參數(shù)是錯(cuò)誤對(duì)象。

5.2 運(yùn)行程序 error.py

1. 啟動(dòng)程序 error.py

$ python error.py

2. 在瀏覽器中訪(fǎng)問(wèn) http://localhost:5000/non-exist-page

3. 觀察瀏覽器的顯示

404 Error

訪(fǎng)問(wèn)一個(gè)不存在的頁(yè)面 /non-exist-page,產(chǎn)生 HTTP 404 錯(cuò)誤,F(xiàn)lask 框架執(zhí)行使用 @errorhandler(404) 注冊(cè)的函數(shù) errorhandler,該函數(shù)返回字符串 ‘404 Error’ 給瀏覽器作為響應(yīng)。

5. 觀察控制臺(tái)的輸出

error_handler(404)
404 Not Found: The requested URL was not found on the server. If
 URL manually please check your spelling and try again.

執(zhí)行 errorhandler 時(shí),首先打印字符串 ‘error_handler(404)’,然后打印 Error 對(duì)象。

6. 源代碼下載

7. 小結(jié)

本小節(jié)講解了鉤子函數(shù)的語(yǔ)法和常見(jiàn)的鉤子函數(shù),對(duì)本小節(jié)講解的重點(diǎn),使用思維導(dǎo)圖概括如下:

圖片描述