摘要:前面兩篇講明了怎么支持多線程以及怎么開啟多線程的這篇來講講當后端接收到請求后是怎么一步步封裝的類中的當應用啟動后會通過接收請求中返回的是方法主要做了兩件事情第一件事是通過的另一個方法返回得到了一個封裝好的對象然后調用中的在最后調用了將請求對
前面兩篇講明了flask怎么支持多線程以及怎么開啟多線程的,這篇來講講當后端接收到請求后是怎么一步步封裝的
Flask類中的wsgi_app()
當應用啟動后WSGI Server會通過Flask.__call__()接收http請求,Flask.__call__()中返回的是wsgi_app()方法,
def wsgi_app(self, environ, start_response): ctx = self.request_context(environ) ctx.push() error = None try: try: 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)
wsgi_app()主要做了兩件事情:
第一件事是通過Flask的另一個方法request_context()返回得到了一個封裝好的RequsetContext對象,
ctx = self.request_context(environ),然后調用RequestContext中的push(),
class RequestContext(object):
def push(self): 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) if hasattr(sys, "exc_clear"): sys.exc_clear() _request_ctx_stack.push(self) self.session = self.app.open_session(self.request) if self.session is None: self.session = self.app.make_null_session()
在最后調用了_request_ctx_stack.push(self),將請求對象推入請求上下文棧中
第二件事是在RequestContext的push()中調用app_ctx = self.app.app_context(),app_ctx.push(),將app推入應用上下文棧,
深究下去時可以發(fā)現(xiàn),在RequestContext中有個app屬性,它在Flask中的request_context(),也就是在wasi_app()中調用self.request_context(environ)時被賦值,
def request_context(self, environ): return RequestContext(self, environ)
可以看到每次都傳入了self,也就是Flask對象,它在RequestContext中賦值給了self.app,所以在RequestContext push()中每次推入應用上下文的app都是同一個
有兩點需要注意:
1.在web runtime情況下,請求上下文和應用上下文,同時存在,同時消亡
2.創(chuàng)建完應用后不會立即生成應用上下文
RequestContext中放了request和session
AppContext中放了g
current_app就是AppContext對象
Local()中的__storage__這個字典格式是{thread_id:{"stack":[
所以LocalStack中的top方法返回的結果有兩個:一個是RequestContext對象,一個是AppContext對象
最后拋兩個問題,下次寫
1.明明一個線程只能處理一個請求,那么棧里的元素永遠是在棧頂,那為什么需要用棧這個結構?用普通變量不行嗎.
2._request_ctx_stack和_app_ctx_stack都是線程隔離的,那么為什么要分開?
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/44731.html
摘要:上次遺留了兩個問題先說一下自己的看法問題明明一個線程只能處理一個請求那么棧里的元素永遠是在棧頂那為什么需要用棧這個結構用普通變量不行嗎和都是線程隔離的那么為什么要分開我認為在的情況下是可以不需要棧這個結構的即使是單線程下也不需要原本我以為在 上次遺留了兩個問題,先說一下自己的看法問題:1.明明一個線程只能處理一個請求,那么棧里的元素永遠是在棧頂,那為什么需要用棧這個結構?用普通變量不行...
摘要:并且棧頂?shù)脑囟际堑恼埱笊舷挛暮蛻蒙舷挛闹?,我們再在這個環(huán)境中嵌套的應用上下文。這時查看兩個棧的內容,發(fā)現(xiàn)兩個棧中只有的請求的請求上下文對象和應用上下文對象。而等一直指向棧頂?shù)恼埱笊舷挛膶ο?,分別引用請求上下文的和。 在Flask中處理請求時,應用會生成一個請求上下文對象。整個請求的處理過程,都會在這個上下文對象中進行。這保證了請求的處理過程不被干擾。處理請求的具體代碼如下: de...
摘要:如果設置為,命令將激活模式,執(zhí)行會啟用交互式調試器和代碼自動重載。也可以通過變量單獨控制,表示啟用,表示禁用通過設置環(huán)境變量略通過設置環(huán)境變量略自定義命令命令基于庫實現(xiàn)。 應用發(fā)現(xiàn) flask命令在Flask庫安裝后可使用,使用前需要正確配置FLASK_APP環(huán)境變量以告知用戶程序所在位置。不同平臺設置方式有所不同。 Unix Bash (Linux, Mac, etc.): $ ex...
摘要:本文就主要針對一個應用的運行過程進行簡要分析,后續(xù)文章還會對框架的一些具體問題進行分析。所有的請求處理過程,都會在這個上下文對象中進行。和一些全局變量注意當進入這個上下文對象時,會觸發(fā)。 相信很多初學Flask的同學(包括我自己),在閱讀官方文檔或者Flask的學習資料時,對于它的認識是從以下的一段代碼開始的: from flask import Flask app = Flask(...
摘要:瀏覽器渲染進程瀏覽器內核進程,內部是多線程的默認每個頁面一個進程,互不影響。事件觸發(fā)線程歸屬于瀏覽器而不是引擎,用來控制事件循環(huán)可以理解成引擎自己都忙不過來,需要瀏覽器另開線程協(xié)助。 線程和進程 進程和線程的概念可以這樣理解: 進程是一個工廠,工廠有它的獨立資源--工廠之間相互獨立--線程是工廠中的工人,多個工人協(xié)作完成任務--工廠內有一個或多個工人--工人之間共享空間 工廠有多個工人...
閱讀 2524·2021-09-26 10:18
閱讀 3398·2021-09-22 10:02
閱讀 3206·2019-08-30 15:44
閱讀 3335·2019-08-30 15:44
閱讀 1841·2019-08-29 15:25
閱讀 2585·2019-08-26 14:04
閱讀 2050·2019-08-26 12:15
閱讀 2447·2019-08-26 11:43