深入 Flask 原始碼理解 Context

發表於2016-04-23

知乎問題 程式設計中什麼是「Context(上下文)」 已經能夠簡單地說明什麼是 Context,它是一個程式需要的外部物件,類似於一個全域性變數。而這個變數的值會根據提供的值而改變。
Flask 中有分為請求上下文和應用上下文:

物件 Context型別 說明
current_app AppContext 當前的應用物件
g AppContext 處理請求時用作臨時儲存的物件
request RequestContext 請求物件,封裝了Http請求的內容
session RequestContext 用於儲存請求之間需要記住的值

Flask 分發請求之前啟用程式請求上下文,請求處理完成後再將其刪除。

Flask 中的 Context 是通過棧來實現。


Flask 的 Context 實現

Flask 的核心功能依賴於 Werkzeug 庫。

_app_ctx_stack & _request_ctx_stack

這兩種棧定義在 flask/global.py 中。

首先需要了解一下 Werkzeug 中關於 LcoalStack 的相關內容。

Local

Local 是定義了一個 __storage__ 字典,其中的鍵為 threadid 值。

LocalStack

LocalStack 則內部維護一個 Local 例項。主要的作用是將 Local 維護的 __storage__ 字典中鍵為 __ident_func__() 對應的值定義為 {"stack" : [] }

LocalProxy

LocalProxy類是一個代理類,應用到設計模式當中的代理模式。簡單地講,我們不需要去了解當前的環境,而直接去操作這個 Proxy 類,這個 Proxy 類會將所有的操作反饋給正確的物件。

request & RequestContext

Flask 原始碼中關於 request 的定義:

從原始碼可以看出,request_request_ctx_stack 棧頂元素的一個屬性。實際上 _request_ctx_stack 棧中的元素是 ReuqestContext 物件的例項, 而 ReuqestContext 中包含了 request 請求的所有資訊,包括 Session 資訊。

這裡傳入的 app,就是 Flask 的程式例項。
RequestContext 例項的建立在 Flask 類方法中。

Flask 中 Request 物件繼承了 Werkzeug 中的 Request 物件。
上述程式碼涉及到 WSGI,它強調 Appication 必須是一個可呼叫物件。
後期的工作之一是瞭解 WSGI

Session

在 session.py 檔案中定義了 有關Session的內容。Flask 中 Session 是構建在 Cookie 上面的。其中定義了關於 Session 的介面。

如下程式碼則是 session 的應用。

sessionRequestContext 中屬性,所以代理說明如下:

current_app & g

一般來講, 在 Flask Web 開發時, Flask的例項是延遲建立的。也就是說 AppContext還沒有壓入 _app_ctx_stack 中,所以我們在編寫程式碼時,是無法獲取完整的 Flask 例項的屬性。而當使用者訪問時,程式的例項已經初始化完成了,因此我們採用 current_app代理獲取當前 app。這僅僅是我的個人理解。實際上這是解決 多個 Flask 例項執行的問題

current_app是獲取 _app_ctx_stack 棧頂 AppContext例項元素的代理.

flask.g 是儲存一下資源資訊的,如資料庫連線資訊。更多應用的則是體現在 Flask 擴充套件當中。

上述程式碼存在一個疑問是 g 物件是基於請求的,每次請求都會重置。那麼 g 為什麼不是 RequestContext 而是 AppContext ?
flask.g API 文件 中說明了 g 變數的改動。

相關文章