Werkzeug 庫以及 wrapper 模塊
點擊
上方藍字
,快速關注我們)
來源:fanchunke
fanchunke.me/Flask/Werkzeug庫簡介/
如有好文章投稿,請點擊 → 這裡了解詳情
簡介
Werkzeug是一個Python寫成的WSGI工具集。它遵循WSGI規範,對伺服器和Web應用之間的「中間層」進行了開發,衍生出一系列非常有用的Web服務底層模塊。關於Werkzeug功能的最簡單的一個例子如下:
from werkzeug.wrappers import Request, Response
def application(environ, start_response):
request = Request(environ)
response = Response("Hello %s!" % request.args.get("name", "World!"))
return response(environ, start_response)
if __name__ == "__main__":
from werkzeug.serving import run_simple
run_simple("localhost", 4000, application)
運行上面的例子,當在瀏覽器輸入http://localhost:4000/就會向本地的伺服器發出一個請求。在請求的過程中,werkzeug主要做了下面幾件事情:
根據伺服器和WSGI伺服器產生的environ環境信息,封裝一個Request實例,這個實例包含請求的所有信息;
Web應用根據封裝的Request實例信息,產生一個Response實例(上述例子只是輸出一段字元串)。這個Response實例是一個可調用的WSGI應用;
上一步驟產生的可調用應用對象response調用response(environ, start_response)生成響應信息並發回客戶端。調用函數是由WSGI規範規定的。
以上過程很好地將伺服器和web應用分離開來:伺服器不用考慮請求信息怎麼被解析給web應用,以及後續怎麼和web應用通信;web應用也不用考慮怎麼將響應信息返回給伺服器。伺服器要做的只是提供web應用所需的請求信息,web應用提供的也只是響應信息,中間的處理過程werkzeug可以幫助完成。
wrappers模塊
Werkzeug庫中的wrappers模塊主要對request和response進行封裝。request包含了客戶端發往伺服器的所有請求信息,response包含了web應用返回給客戶端的所有信息。wrappers模塊對請求和響應的封裝簡化了客戶端、伺服器和web應用通信的流程。本文主要介紹wrappers模塊中重要的類。
BaseRequest
BaseRequest是一個非常基礎的請求類,它可以和其他的「混合」類結合在一起構建複雜的請求類。只要傳遞一個環境變數environ(由WSGI伺服器根據請求產生),便可以構造一個BaseRequest實例。其構造函數如下:
def
__init__
(
self
,
environ
,
populate_request
=
True
,
shallow
=
False
)
:
self
.
environ
=
environ
if
populate_request
and
not
shallow
:
self
.
environ
[
"werkzeug.request"
]
=
self
self
.
shallow
=
shallow
初始化後,形成的實例request便具有了一些屬性可以訪問,這些屬性只能以「只讀」的方式訪問。例如:
url_charset
want_form_data_parsed
stream
args
data
form
values
files
cookies
headers
path
full_path
script_root
url
base_url
url_root
host_url
host
access_route
remote_addr
BaseRequest中還有兩個類方法比較常用:
from_values(cls, *args, kwargs)**
@
classmethod
def
from_values
(
cls
,
*
args
,
**
kwargs
)
:
"""Create a new request object based on the values provided. If
environ is given missing values are filled from there. This method is
useful for small scripts when you need to simulate a request from an URL.
Do not use this method for unittesting, there is a full featured client
object (:class:`Client`) that allows to create multipart requests,
support for cookies etc.
This accepts the same options as the
:class:`~werkzeug.test.EnvironBuilder`.
.. versionchanged:: 0.5
This method now accepts the same arguments as
:class:`~werkzeug.test.EnvironBuilder`. Because of this the
`environ` parameter is now called `environ_overrides`.
:return: request object
"""
from
werkzeug
.
test
import
EnvironBuilder
charset
=
kwargs
.
pop
(
"charset"
,
cls
.
charset
)
kwargs
[
"charset"
]
=
charset
builder
=
EnvironBuilder
(
*
args
,
**
kwargs
)
try
:
return
builder
.
get_request
(
cls
)
finally
:
builder
.
close
()
這個類方法可以根據提供的參數構建一個請求。
application(cls, f)
@
classmethod
def
application
(
cls
,
f
)
:
"""Decorate a function as responder that accepts the request as first
argument. This works like the :func:`responder` decorator but the
function is passed the request object as first argument and the
request object will be closed automatically::
@Request.application
def my_wsgi_app(request):
return Response("Hello World!")
:param f: the WSGI callable to decorate
:return: a new WSGI callable
"""
#: return a callable that wraps the -2nd argument with the request
#: and calls the function with all the arguments up to that one and
#: the request. The return value is then called with the latest
#: two arguments. This makes it possible to use this decorator for
#: both methods and standalone WSGI functions.
def
application
(
*
args
)
:
request
=
cls
(
args
[
-
2
])
with
request
:
return
f
(
*
args
[
:-
2
]
+
(
request
,))(
*
args
[
-
2
:
])
return
update_wrapper
(
application
,
f
)
這個類方法是一個裝飾器,可以用來裝飾WSGI可調用對象或函數。
以上屬性和方法的具體用法可以參考Request——werkzeug文檔。
BaseResponse
BaseResponse類是一個響應類,用它可以封裝一個response對象。response對象最大的特點是它是一個WSGI應用。
在之前介紹WSGI規範的文章中曾介紹過Web伺服器網關,它簡化了伺服器和web應用之間的通信過程,它要求伺服器和web應用要遵循WSGI規範進行開發。對於web應用而言,應用應該實現一個函數或者一個可調用對象,這樣WSGI伺服器可以通過調用myWebApp(environ, start_response)從web應用獲得響應內容。
response響應對象就是這樣一個WSGI應用對象。在其實現過程中有一個__call__方法,可以實現對一個response對象的調用。代碼如下:
def
__call__
(
self
,
environ
,
start_response
)
:
"""Process this response as WSGI application.
:param environ: the WSGI environment.
:param start_response: the response callable provided by the WSGI
server.
:return: an application iterator
"""
app_iter
,
status
,
headers
=
self
.
get_wsgi_response
(
environ
)
start_response
(
status
,
headers
)
return
app_iter
這樣,我們就可以很清楚地理解WSGI應用的實現過程。下面是一個非常簡單的WSGI應用。
from
werkzeug
.
wrappers
import
Request
,
Response
def
application
(
environ
,
start_response
)
:
request
=
Request
(
environ
)
response
=
Response
(
"Hello %s!"
%
request
.
args
.
get
(
"name"
,
"World!"
))
return
response
(
environ
,
start_response
)
上面的小例子的實現步驟分析:
根據傳入web應用的environ構造請求對象request;
web應用構造響應對象response;
調用響應對象response。調用過程中產生三個值:app_iter、status、headers,其中status和headers作為參數傳遞給函數start_response用於生成響應報文首行的相關信息,而app_iter作為響應的內容(它是一個可迭代對象)返回給WSGI網關;
WSGI網關將返回的信息組成響應首行、響應首部、響應主體等,形成響應報文發回給客戶端。
BaseResponse類中還有一些屬性和方法,以下屬性和方法的具體用法可以參考Response——werkzeug文檔。
屬性
status_code
status
data
is_stream
is_sequence
······
方法
call_on_close(func)
close()
freeze()
force_type() 類方法
from_app() 類方法
set_data()
get_data()
_ensure_sequence()
make_sequence()
iter_encoded()
calculate_content_length()
set_cookie()
delete_cookie()
get_wsgi_headers(environ)
get_app_iter(environ)
get_wsgi_response(environ)
__call__(environ, start_response)
······
Mixin類
BaseRequest類和BaseResponse類是請求和響應最基礎的類。wrappers模塊中還提供了一些Mixin類,用於擴展請求類和響應類。
有關請求類的Mixin類
有關請求類的Mixin類主要有:
AcceptMixin類 ——請求報文中關於客戶端希望接收的數據類型的類。
ETagRequestMixin類 ——請求報文中關於Etag和Cache的類。
UserAgentMixin類 ——請求報文中關於user_agent的類。
AuthorizationMixin類 ——請求報文中關於認證的類。
CommonRequestDescriptorsMixin類 ——通過這個類可以獲取請求首部中的相關信息。
有關響應類的Mixin類
有關響應類的Mixin類主要有:
ETagResponseMixin類 ——為響應增加Etag和Cache控制的類。
ResponseStreamMixin類 ——為響應可迭代對象提供一個「只寫」的介面的類。
CommonResponseDescriptorsMixin類 ——通過這個類可以獲取響應首部中的相關信息。
WWWAuthenticateMixin類 ——為響應提供認證的類。
Request和Response
終於講到Request類和Response類了。
Request類繼承自BaseRequest類,並且結合一些請求相關的Mixin類,具體如下:
class
Request
(
BaseRequest
,
AcceptMixin
,
ETagRequestMixin
,
UserAgentMixin
,
AuthorizationMixin
,
CommonRequestDescriptorsMixin
)
Response類繼承自BaseResponse類,並且結合一些響應相關的Mixin類,具體如下:
class
Response
(
BaseResponse
,
ETagResponseMixin
,
ResponseStreamMixin
,
CommonResponseDescriptorsMixin
,
WWWAuthenticateMixin
)
至此,可以從wrappers模塊中引入Request類和Response用於構建請求對象和響應對象。
看完本文有收穫?請轉
發分享給更多人
關注「Python開發者」,提升Python技能


※這裡有 10 個省時間的 PyCharm 技巧
※限免100人|魔鏡數據訓練營招生開始,帶你從0到1打造數據產品
※用分布式爬蟲搞點數據回來!
※Python 爬蟲神器 PyQuery 的使用方法
※教你搭建一個好看的 Jupyter 環境
TAG:Python開發者 |