摘要:實現(xiàn)一個進(jìn)程中擁有多個應(yīng)用上下文機(jī)制依賴的數(shù)據(jù)結(jié)構(gòu)上下文機(jī)制的實現(xiàn)基于的。
什么是上下文?
flask框架中的上下文本質(zhì)上就是兩個類,我們可以先看一下他的初始化函數(shù):
應(yīng)用上下文
class AppContext(object): """The application context binds an application object implicitly to the current thread or greenlet, similar to how the :class:`RequestContext` binds request information. The application context is also implicitly created if a request context is created but the application is not on top of the individual application context. """ def __init__(self, app): self.app = app self.url_adapter = app.create_url_adapter(None) self.g = app.app_ctx_globals_class() # Like request context, app contexts can be pushed multiple times # but there a basic "refcount" is enough to track them. self._refcnt = 0
請求上下文
class RequestContext(object): def __init__(self, app, environ, request=None): self.app = app if request is None: request = app.request_class(environ) self.request = request self.url_adapter = app.create_url_adapter(self.request) self.flashes = None self.session = None self._implicit_app_ctx_stack = [] self.preserved = False self._preserved_exc = None self._after_request_functions = [] self.match_request()為什么設(shè)計上下文這樣的機(jī)制?
詳細(xì)解釋可參考:
https://blog.tonyseek.com/pos...
多線程環(huán)境下,實現(xiàn)線程之間的隔離
類似Thread Local ,每個線程對一個 Thread Local 對象的修改都不會影響其他線程。這種對象的實現(xiàn)原理也非常簡單,只要以線程的 ID 來保存多份狀態(tài)字典即可,就像按照門牌號隔開的一格一格的信箱。
實現(xiàn)一個 Python 進(jìn)程中擁有多個應(yīng)用
from werkzeug.wsgi import DispatcherMiddleware from biubiu.app import create_app from biubiu.admin.app import create_app as create_admin_app application = DispatcherMiddleware(create_app(), { "/admin": create_admin_app() })上下文機(jī)制依賴的數(shù)據(jù)結(jié)構(gòu)
flask上下文機(jī)制的實現(xiàn)基于 Werkzeug 的 Local Stack 。
閱讀源碼,Local Stack又依賴于local類,我們發(fā)現(xiàn)Local類的本質(zhì)是一個字典和一個獲取到線程id的函數(shù)。
class Local(object): __slots__ = ("__storage__", "__ident_func__") def __init__(self): object.__setattr__(self, "__storage__", {}) object.__setattr__(self, "__ident_func__", get_ident)
而LocalStack在Local類的基礎(chǔ)上又實現(xiàn)了棧的功能。
class LocalStack(object): def __init__(self): self._local = Local()
flask中應(yīng)用上下文棧和請求上下文棧正是基于上面的LocalStack類
_request_ctx_stack = LocalStack() _app_ctx_stack = LocalStack()
下面我們通過一些實驗來進(jìn)一步學(xué)習(xí)flask的執(zhí)行過程:
In [1]: from flask.globals import _app_ctx_stack, _request_ctx_stack In [2]: from flask import Flask In [3]: app = Flask(__name__) In [4]: _app_ctx_stack._local.__storage__ Out[4]: {} In [5]: _request_ctx_stack._local.__storage__ Out[5]: {} In [6]: req_ctx = app.test_request_context() In [7]: req_ctx.push() In [8]: _request_ctx_stack._local.__storage__ Out[8]: {: {"stack": [ ]}} In [9]: _app_ctx_stack._local.__storage__ Out[9]: { : {"stack": [ ]}}
我們可以看到一開始上下文均為空,test_request_context()函數(shù)會生成一個請求上下文,我們通過push讓它入棧,之后兩個上下文都有了內(nèi)容,為什么_app_ctx_stack中也有內(nèi)容呢?
我們可以看一下源碼,第一次請求上下文push時,app_ctx如果為None,就會調(diào)用_implicit_app_ctx_stack_添加一個應(yīng)用上下文。
app_ctx = _app_ctx_stack.top if app_ctx is None or app_ctx.app != self.app: app_ctx = self.app.app_context() app_ctx.push() self._implicit_app_ctx_stack.append(app_ctx) else: self._implicit_app_ctx_stack.append(None)
這里我們就可以解釋flask中wsgi_app這部分代碼,每次web服務(wù)器為flask提供了http請求的environ變量,flask就會創(chuàng)建一個request_context對象,執(zhí)行push()
之后上下文對象就會進(jìn)入_request_ctx_stack中,并在執(zhí)行處理函數(shù)之后會自動pop,
所以我們說請求上下文的生命周期就是一次請求的過程。
def wsgi_app(self, environ, start_response): ctx = self.request_context(environ) error = None try: try: ctx.push() response = self.full_dispatch_request() except Exception as e: error = e response = self.handle_exception(e) except: error = sys.exc_info()[1] raise return response(environ, start_response) finally: if self.should_ignore_error(error): error = None ctx.auto_pop(error)
整體流程可參考:
https://www.jianshu.com/p/2a2...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/41133.html
摘要:我們的論壇項目就使用了該框架。此外,麥子學(xué)院也有一個入門視頻教程,一共小時的視頻教程,涵蓋開發(fā)的方方面面,包括環(huán)境的搭建,語法介紹,項目結(jié)構(gòu)的組織,全球化,單元測試等內(nèi)容。博客地址更多閱讀的機(jī)制三個框架的對比 前面兩篇文章中我們已經(jīng)了解 Web(HTTP)服務(wù)器,Web應(yīng)用程序,Web框架,WSGI這些 Python Web 開發(fā)中的概念。我們知道,Web框架通過將不同Web應(yīng)用程序中...
摘要:中的配置,都是通過來控制那么究竟是什么再來看函數(shù)而是什么再轉(zhuǎn)向看的源碼,可以看到類繼承于字典也就是說的就是一個特殊的字典,用于保存配置項。 config flask中的配置,都是通過config來控制那么config究竟是什么? self.config = self.make_config(instance_relative_config) 再來看make_config函數(shù): def ...
摘要:主要的作用是將維護(hù)的字典中鍵為對應(yīng)的值定義為。如果沒有,則會將當(dāng)前到中,同時將加入列表中否則添加。注意清理之后的動作。上述代碼涉及到,它強(qiáng)調(diào)必須是一個可調(diào)用對象。后期的工作之一是了解。這僅僅是我的個人理解。實際上這是解決多個實例運行的問題。 Flask 中的上下文對象 知乎問題 編程中什么是「Context(上下文)」 已經(jīng)能夠簡單地說明什么是 Context,它是一個程序需要的外部對...
摘要:中的實現(xiàn)是基于。打開源碼的文件,我們可以看到最后的接口類中,主要有兩個函數(shù)。這個系列就此完結(jié)。 flask中session的實現(xiàn)是基于cookie。打開flask源碼的session.py文件,我們可以看到最后的接口類中,主要有open_session,save_session兩個函數(shù)。 class SecureCookieSessionInterface(SessionInterfa...
閱讀 1296·2021-11-11 16:55
閱讀 3146·2021-08-16 11:00
閱讀 3029·2019-08-30 15:56
閱讀 3523·2019-08-30 11:24
閱讀 3494·2019-08-30 11:05
閱讀 3631·2019-08-29 15:15
閱讀 2708·2019-08-26 13:57
閱讀 2685·2019-08-23 18:17