引言
本文主要梳理了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:
1 2 3 4 5 6 7 8 |
# 程式碼摘選自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
的程式碼如下:
1 2 3 4 |
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
類的定義中:
1 2 3 4 |
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 contextFlask
每響應一個http請求,就會建立一個Request
物件,這個request物件對應的上下文,就是request context