亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Flask的上下文管理詳解

發布時間:2021-09-17 16:13:00 來源:億速云 閱讀:106 作者:chen 欄目:編程語言

本篇內容介紹了“Flask的上下文管理詳解”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

Flask線程間上下文安全

Falsk完成線程安全的原理,是在啟動之后進程里維護request棧和app棧,棧是通過線程ID來保證每個請求的線程安全。

實現主要依賴三個類Local,LocalStack和LocalProxy,下面看一下具體的實現原理

三個類構建本地數據

1. Local

先看Local的源碼,實質并不是Flask中定義的,而是Flask依賴的werkzeug庫所定義。

可以看到其定義的兩個屬性__storage__, __ident_func__以及三個方法__getattr__,__setattr__,__release_local__。

1.屬性__storage__是多層級字典,第一層key是隱含的線程ID或者協程ID,第二層的key是實際使用的關鍵字

2.屬性__ident_func__可以看到是get_ident函數,get_ident函數要么是通過thread庫獲取當前執行單元的線程ID,要么是通過greenlet庫獲取當前執行協程的協程ID。

另外可以看到Local這個類的三個方法,實質是通過重寫Python內置函數__setattr__和__getattr__來實現線程或者協程間數據隔離

1.獲取local某屬性時如:local.age實質觸發的是__getattr__方法先獲取到當前線程ID——__ident_func__函數獲取,然后在__storage__字典中找到線程ident對應的結果集從獲取到的結果中再查找age屬性

2.設置local某屬性時如:local.age = 12 實際觸發的是__setattr__方法先獲取到當前線程ID——__ident_func__函數獲取,然后在__storage__字典設置相應的屬性字典集

另一個__release_local__方法就是將相應的線程數據刪除。

畫個簡圖比較起來更直觀一些。

Flask的上下文管理詳解

主線程中生成一個對象local=Local(),三個線程中進行相同的操作local.no=每個線程對應的數。為每個線程都開辟一個存儲,所以誰來取或者存就找到自己對應中的位置,雖然取得key都一樣,但是每次存取都是只關于自己的值。

2. LocalStack

LocalStack也是定義在Flask所依賴的werkzeug庫,從字面意思來理解,它就是Local的堆棧操作,看一下源碼如何定義。

LocalStack實質就是圍繞著Local來進行操作,根據上面我們讀完Local的源碼可以看到,

  1. LocalStack定義了一個Local對象

  2. 給這個對象設置了一個stack屬性,且這個屬性是一個列表

  3. LocalStack中定義了對這個列表進行壓棧,出棧等方法

  4. 給類中的Local對象提供了自定義ident_func的方法

3. LocalProxy

LocalProxy字面意思就是做一個Local的代理,我們先從一個request的定義來看LocalProxy的用法,然后結合源碼來看LocalProxy到底是用來做什么?

類中稍微有些難理解的就是關于object.__setattr__(self, “_LocalProxy__local”, local)的作用,實際就是給self設置一個__local屬性。這是Python類中關于私有變量的定義。可以看Python的官方定義python私有變量。

可以看到這個類將所有Python類所內置的方法都進行重寫,重寫后所有的操作都是基于類中所定義的_get_current_object方法返回的對象進行操作。

而這個方法中返回值就是初始化時所給定的local對象執行返回的結果。如果創建時指定的不是Local對象,則直接執行此方法。如果給定的是Local對象,則根據類名查找對應的對象。

現在這個比較抽象,這個代理到底是做的什么? 我們結合Flask定義全局的request對象來看。假如我們想獲取請求的方法是什么,那我們使用的就是request.method。

下面是request定義的源碼

  1. 根據LocalProxy的源碼中重寫的__getattr__方法,先執行_get_current_object方法獲取到對象,然后再獲取返回對象method屬性。

  2. 創建LocalProxy時傳遞的函數是_lookup_req_object的偏函數,實際就是_lookup_req_object且name=request

  3. 再LocalProxy中__local就是一個函數,所以在執行_get_current_object就是執行_lookup_req_object且name=request返回的值,然后再取其method屬性

  4. 此時再執行_lookup_req_object函數,從_request_ctx_stack獲取top的request

使用Proxy可以簡單快捷的使用request.method獲取相應的值,其核心就是每次獲取時都會執行對應的函數,而函數中每次返回的值都是線程安全。保證數據正確且優雅。 否則我們每次都去執行一個函數來獲取其值,然后再取其屬性。

“Flask的上下文管理詳解”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

晋中市| 宾阳县| 雷州市| 武宣县| 平塘县| 洪湖市| 东辽县| 两当县| 东山县| 三亚市| 颍上县| 通山县| 湄潭县| 杂多县| 临洮县| 新乐市| 海盐县| 保靖县| 甘谷县| 庄浪县| 广元市| 资阳市| 雷州市| 东乡县| 安溪县| 鄂托克前旗| 万源市| 潍坊市| 维西| 永胜县| 洞口县| 舞钢市| 大连市| 镇宁| 白城市| 西乌珠穆沁旗| 木里| 漳州市| 巧家县| 灯塔市| 泉州市|