詳解Python的Flask框架中的signals信號機(jī)制
Flask 提供了信號(Signals)功能,是一種消息分發(fā)機(jī)制。類似于鉤子(Hooks)。使用信號功能可以降低程序的耦合,分解復(fù)雜的業(yè)務(wù)模型。例如在更新了產(chǎn)品數(shù)據(jù)后,可以發(fā)送一個(gè)信號。當(dāng)有需要對產(chǎn)品數(shù)據(jù)進(jìn)行處理的功能時(shí),就可以捕獲信號進(jìn)行處理。比如要建立產(chǎn)品緩存,或是更新搜索索引等。
定義信號
Flask 信號功能使用了 Blinker 模塊,所以需要先安裝 Blinker 模塊
pip install blinker
定義一個(gè)信號:
from blinker import Namespace product_saved = Namespace()
也可以使用 Flask 包裝的 singles 對象:
from flask.singles import Namespace
發(fā)送信號
發(fā)送信號需要帶上 app 實(shí)例方法,示例如下:
product_saved.send(app, product=product)
app 后面可以添加要傳遞的參數(shù),但必須以 name=value 的格式,不支持使用單個(gè)變量名的方式。
收接信號
接收信號可以使用 connect_via 裝飾器函數(shù):
@product_saved.connect_via(app) def updateCache(app, product): print(product)
Flask 中有以下核心信號:
1.flask.template_rendered
這個(gè)信號發(fā)送于一個(gè)模板被渲染成功后。信號傳遞的template是模板的實(shí)例,context是環(huán)境對象是一個(gè)字典。
訂閱示例:
def log_template_renders(sender, template, context, **extra):
sender.logger.debug('Rendering template "%s" with context %s',
template.name or 'string template',
context)
from flask import template_rendered
template_rendered.connect(log_template_renders, app)
2.flask.request_started
這個(gè)信號發(fā)送于請求開始之前,且請求環(huán)境設(shè)置完成之后。因?yàn)檎埱蟓h(huán)境已經(jīng)綁定, 所以訂閱者可以用標(biāo)準(zhǔn)的全局代理,如 request 來操作請求。
訂閱示例:
def log_request(sender, **extra):
sender.logger.debug('Request context is set up')
from flask import request_started
request_started.connect(log_request, app)
flask.request_finished
這個(gè)信號發(fā)送于向客戶端發(fā)送響應(yīng)之前。信號傳遞的response為將要發(fā)送的響應(yīng)。
訂閱示例:
def log_response(sender, response, **extra):
sender.logger.debug('Request context is about to close down. '
'Response: %s', response)
from flask import request_finished
request_finished.connect(log_response, app)
flask.got_request_exception
這個(gè)信號發(fā)送于請求進(jìn)行中發(fā)生異常的時(shí)候。它的發(fā)送 早于 標(biāo)準(zhǔn)異常處理介于。 在調(diào)試模式下,雖然沒有異常處理,但發(fā)生異常時(shí)也發(fā)送這個(gè)信號。信號傳遞的exception是異常對象。
訂閱示例:
def log_exception(sender, exception, **extra):
sender.logger.debug('Got exception during processing: %s', exception)
from flask import got_request_exception
got_request_exception.connect(log_exception, app)
flask.request_tearing_down
這個(gè)信號發(fā)送于請求崩潰的時(shí)候,不管是否引發(fā)異常。目前,偵聽此信號的函數(shù)在一般 崩潰處理器后調(diào)用,但是沒有什么東西可用。
訂閱示例:
def close_db_connection(sender, **extra): session.close()from flask import appcontext_tearing_down request_tearing_down.connect(close_db_connection, app)
在 Flask 版本 0.9 中,這還會傳遞一個(gè)exc關(guān)鍵字參數(shù),如果這個(gè)參數(shù)存在的話。 這個(gè)參數(shù)是引發(fā)崩潰的異常的引用。
3.flask.appcontext_tearing_down
當(dāng)應(yīng)用環(huán)境崩潰時(shí)發(fā)送這個(gè)信號。這個(gè)信號總是會發(fā)送,甚至是因?yàn)橐粋€(gè)異常引發(fā)的 崩潰。偵聽這個(gè)信號的函數(shù)會在常規(guī)崩潰處理器后被調(diào)用,但是你無法回饋這個(gè)信號。
訂閱示例:
def close_db_connection(sender, **extra): session.close()from flask import request_tearing_down appcontext_tearing_down.connect(close_db_connection, app)
這還會傳遞一個(gè)exc關(guān)鍵字參數(shù),如果這個(gè)參數(shù)存在的話。這個(gè)參數(shù)是引發(fā)崩潰的 異常的引用。
4.flask.appcontext_pushed
當(dāng)一個(gè)應(yīng)用的環(huán)境被壓入時(shí),應(yīng)用會發(fā)送這個(gè)信號。這個(gè)信號通常用于在單元測試中 臨時(shí)鉤接信息。例如可以用于改變g對象中現(xiàn)存的資源。
用法示例:
from contextlib import contextmanagerfrom
flask import appcontext_pushed
@contextmanagerdef user_set(app, user):
def handler(sender, **kwargs):
g.user = user
with appcontext_pushed.connected_to(handler, app):
yield
在測試代碼中這樣寫:
def test_user_me(self):
with user_set(app, 'john'):
c = app.test_client()
resp = c.get('/users/me')
assert resp.data == 'username=john'
New in version 0.10.
5.appcontext_popped
當(dāng)一個(gè)應(yīng)用的環(huán)境被彈出時(shí),應(yīng)用會發(fā)送這個(gè)信號。這個(gè)信號通常寫成appcontext_tearing_down 信號。
6.flask.message_flashed
當(dāng)應(yīng)用閃現(xiàn)一個(gè)消息時(shí)會發(fā)出這個(gè)信號。message`參數(shù)是消息內(nèi)容, `category參數(shù)是消息類別。
訂閱示例:
recorded = []def record(sender, message, category, **extra): recorded.append((message, category)) from flask import message_flashed message_flashed.connect(record, app)
小結(jié)
信號可以讓你在一瞬間安全地訂閱它們。例如,這些臨時(shí)的訂閱對測試很有幫助。使用信號時(shí),不要讓信號訂閱者(接收者)發(fā)生異常,因?yàn)楫惓斐沙绦蛑袛唷?/p>
相關(guān)文章
opencv實(shí)現(xiàn)圖像旋轉(zhuǎn)效果
這篇文章主要為大家詳細(xì)介紹了opencv實(shí)現(xiàn)圖像旋轉(zhuǎn)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-03-03
Python庫中可以操作JavaScript盤點(diǎn)解析
這篇文章主要為大家介紹了Python庫之可以操作JavaScript盤點(diǎn)解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06
python sklearn庫實(shí)現(xiàn)簡單邏輯回歸的實(shí)例代碼
Scikit-learn(sklearn)是機(jī)器學(xué)習(xí)中常用的第三方模塊,對常用的機(jī)器學(xué)習(xí)方法進(jìn)行了封裝,這篇文章主要介紹了python sklearn庫實(shí)現(xiàn)簡單邏輯回歸的實(shí)例代碼,需要的朋友可以參考下2019-07-07
python實(shí)現(xiàn)簡易的學(xué)生信息管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)簡易的學(xué)生信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
Python編程實(shí)戰(zhàn)之Oracle數(shù)據(jù)庫操作示例
這篇文章主要介紹了Python編程實(shí)戰(zhàn)之Oracle數(shù)據(jù)庫操作,結(jié)合具體實(shí)例形式分析了Python的Oracle數(shù)據(jù)庫模塊cx_Oracle包安裝、Oracle連接及操作技巧,需要的朋友可以參考下2017-06-06
簡介Python的collections模塊中defaultdict類型的用法
這里我們來簡介Python的collections模塊中defaultdict類型的用法,與內(nèi)置的字典類最大的不同在于初始化上,一起來看一下:2016-07-07

