flask 上下文的實現
引言
本文主要梳理了flask的current_app, request, session, g的實現原理
源碼說明
本文使用flask 0.5 版本
application context 和request context
flask 有兩個context: application context 和 request context
application context | request context | |
---|---|---|
current_app | request | |
g | session |
這里需要通俗地解釋一下 application context 與 request context :
-
application 指的就是當你調用 app = Flask(__name__) 創建的這個對象 app ;
-
request 指的是每次 http 請求發生時, WSGI server (比如gunicorn)調用 Flask.__call__() 之后,在 Flask 對象內部創建的 Request 對象;
-
application 表示用于響應WSGI請求的應用本身, request 表示每次http請求;
-
application 的生命周期大于 request ,一個 application 存活期間,可能發生多次http請求,所以,也就會有多個 request
下面通過源碼了解一下 flask 如何實現這兩種context:
# 代碼摘選自flask 0.5 中的ctx.py文件, 進行了部分刪減 class _RequestContext(object): def __init__(self, app, environ): self.app = app self.request = app.request_class(environ) self.session = app.open_session(self.request) self.g = _RequestGlobals()
flask使用 _RequestContext 的代碼如下:
class Flask(object): def request_context(self, environ): return _RequestContext(self, environ)
在 Flask 類中,每次請求都會調用這個 request_context 函數。這個函數則會創建一個 _RequestContext 對象。
值得注意的是:這個對象在創建時,將 Flask 實例的本身作為實參傳入 _RequestContext 自身,因此,
self.app = Flask() 。
所以,雖然每次http請求都會創建一個 _RequestContext 對象,但是,每次創建的時候都會將同一個 Flask 對象傳入該對象的 app 成員變量,使得:
由同一個 Flask 對象響應的請求所創建的 _RequestContext 對象的 app 成員變量都共享同一個 application
通過在 Flask 對象中創建 _RequestContext 對象,并將 Flask 自身作為參數傳入 _RequestContext 對象的方式,實現了多個 request context 對應一個 application context 的目的。
接下來,看 self.request = app.request_class(environ) 這句。
由于 app 成員變量就是 app = Flask(__name__) 這個對象,所以, app.request_class 就是 Flask.request_class 。
在 Flask 類的定義中:
request_class = Request # Request 是一個類,定義如下: class Request(RequestBase): ...
所以:
self.request = app.request_class(environ) 實際上是創建了一個 Request 對象。
由于,一個http請求對應一個 _RequestContext 對象的創建,而每個 _RequestContext 對象的創建對應一個 Request 對象的創建,所以,每個http請求對應一個 Request 對象。
到這里想必已經很清楚了:
application就是指 app = Flask(__name__) 對象
request就是對應每次http 請求創建的 Request 對象
flask通過 _RequestContext 將 app 與 Request 關聯起來
總結
-
app = Flask(__name__) 創建了application, 這個application對應的上下文,就是 application context
-
Flask 每響應一個http請求,就會創建一個 Request 對象,這個request對象對應的上下文,就是 request context