flask 上下文的實現

jopen 8年前發布 | 9K 次閱讀 Flask Python開發

引言

本文主要梳理了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 contextrequest context

  1. application 指的就是當你調用 app = Flask(__name__) 創建的這個對象 app ;

  2. request 指的是每次 http 請求發生時, WSGI server (比如gunicorn)調用 Flask.__call__() 之后,在 Flask 對象內部創建的 Request 對象;

  3. application 表示用于響應WSGI請求的應用本身, request 表示每次http請求;

  4. 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 關聯起來

總結

  1. app = Flask(__name__) 創建了application, 這個application對應的上下文,就是 application context

  2. Flask 每響應一個http請求,就會創建一個 Request 對象,這個request對象對應的上下文,就是 request context

來自: http://segmentfault.com/a/1190000004223296

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!