接觸Python也有一段時間了,Python相關的框架和模塊也接觸了不少,希望把自己接觸到的自己 覺得比較好的設計和實現分享給大家,于是取了一個“Charming Python”的小標,算是給自己開了一個頭吧, 希望大家多多批評指正。 :)
from flask import request
Flask 是一個人氣非常高的Python Web框架,筆者也拿它寫過一些大大小小的項目,Flask 有一個特性我非常的喜歡,就是無論在什么地方,如果你想要獲取當前的request對象,只要 簡單的:
代碼如下:
from flask import request
# 從當前request獲取內容
request.args
request.forms
request.cookies
... ...
非常簡單好記,用起來也非常的友好。不過,簡單的背后藏的實現可就稍微有一些復雜了。 跟隨我的文章來看看其中的奧秘吧!
兩個疑問?
在我們往下看之前,我們先提出兩個疑問:
疑問一 : request ,看上去只像是一個靜態的類實例,我們為什么可以直接使用request.args 這樣的表達式來獲取當前request的args屬性,而不用使用比如:
代碼如下:
from flask import get_request
# 獲取當前request
request = get_request()
get_request().args
這樣的方式呢?flask是怎么把request對應到當前的請求對象的呢?
疑問二 : 在真正的生產環境中,同一個工作進程下面可能有很多個線程(又或者是協程), 就像我剛剛所說的,request這個類實例是怎么在這樣的環境下正常工作的呢?
要知道其中的秘密,我們只能從flask的源碼開始看了。
源碼,源碼,還是源碼
首先我們打開flask的源碼,從最開始的__init__.py來看看request是怎么出來的:
代碼如下:
# File: flask/__init__.py
from .globals import current_app, g, request, session, _request_ctx_stack
# File: flask/globals.py
from functools import partial
from werkzeug.local import LocalStack, LocalProxy
def _lookup_req_object(name):
top = _request_ctx_stack.top
if top is None:
raise RuntimeError('working outside of request context')
return getattr(top, name)
# context locals
_request_ctx_stack = LocalStack()
request = LocalProxy(partial(_lookup_req_object, 'request'))
我們可以看到flask的request是從globals.py引入的,而這里的定義request的代碼為 request = LocalProxy(partial(_lookup_req_object, 'request')) , 如果有不了解 partial是什么東西的同學需要先補下課,首先需要了解一下 partial 。
不過我們可以簡單的理解為 partial(func, 'request') 就是使用 'request' 作為func的第一個默認參數來產生另外一個function。
所以, partial(_lookup_req_object, 'request') 我們可以理解為:
新聞熱點
疑難解答