上下文管理:
- 請求上下文 (ctx=RequestContext()) : request/session
- App上下文 (app_ctx=AppContext()) : app/g
1. 請求進來執行 __call__ 方法。
2. __call__ 方法調用 wsgi_app。
3. wsgi_app:
- (1)實例化兩個方法:
ctx = RequestContext(request,session)
app_ctx = AppContext(app,g)
- (2) 調用push方法(push方法實例化):
_app_ctx_stack = LocalStack() --> local = Local() --> __storage__ = {線程號:{stack:[app_ctx]}}
_request_ctx_stack = LocalStack() --> local = Local() --> __storage__ = {線程號:{stack:[ctx]}}
- PS:
_app_ctx_stack = LocalStack() 和 _request_ctx_stack = LocalStack() 執行過程當中會有:
push(), top(), pop() 方法來維護
3.5 在這個地方可能會執行 @app.before_request 等特殊裝飾器
4. 視圖函數:
- 調用 request.method --> request = LocalProxy(partial(_lookup_req_object, 'request'))
- 調用 session['q'] --> session = LocalProxy(partial(_lookup_req_object, 'session'))
- request 和 session 會調用各自的偏函數,偏函數找到 top 方法, top方法返回 ctx.request/ctx.session,
而後偏函數會將ctx結果返回到上面兩個方法中(LocalProxy), 在LocalProxy方法中再次取值(ctx.request.method/ctx.session['q']), 再將取出來的值返回到視圖
- 調用 current_app --> current_app = LocalProxy(_find_app)
- 調用 g --> g = LocalProxy(partial(_lookup_app_object, 'g'))
- current_app 和 g 也是會調用各自的偏函數, 偏函數找到 top 方法, top方法返回 app_ctx.app/app_ctx.g,
而後偏函數會將app_ctx結果返回到上面兩個方法中(LocalProxy), 在LocalProxy方法中再次取值(app_ctx.app/app_ctx.g.xx), 再將取出來的值返回到視圖
5. 視圖函數處理完畢以後, 返回瀏覽器以前:
- 在這個過程當中, 會調用 pop() 方法:
- ctx.pop() : 經過pop方法去到 local = Local() 中將 __storage__ = {線程號:{stack:[ctx]}} 中的 ctx刪掉
- app_ctx.pop() : 經過pop方法去到 local = Local() 中將 __storage__ = {線程號:{stack:[app_ctx]}} 中的 app_ctx刪掉
5.5 在這個地方可能會執行 @app.after_request 等特殊裝飾器
6. 返回給用戶瀏覽器。
### g 的理解 ###
概念:
一次請求生命週期中生效的g
1. g 的生命週期:
當有請求的時候, 就會爲這個請求建立一個 g, 當這個請求結束的時候, 就會清除這個 g
注: 有一個請求就建立一個 g, 且只能在同一個請求中使用
2. 多線程並不會影響 g, 由於每個請求就會在 __storage__ 中建立一個惟一的線程號,
這個線程號對應的字典中的app_ctx也是當前這個請求的, 是徹底獨立的內存空間。瀏覽器