Werkzeug 是一個WSGI工具包,也能夠做爲一個Web框架的底層庫。html
在介紹Werkzeug以前,先介紹一下 WSGI(Python Web Server Gateway Interface),它爲Python語言定義的Web服務器和Web應用程序或框架之間的一種簡單而通用的接口。這是一個規範,描述了web server如何與web application交互、web application如何處理請求,該規範的具體描述在PEP3333,強烈推薦先閱讀 PEP3333 再回頭來閱讀本文。python
WSGI 分爲兩個部分:web
能夠經過下面兩張圖片來梳理一下它們之間的調用關係:redis
先從一份示例代碼理解:apache
def application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/plain')]) return ['Hello World!']
一個最基本的 WSGI 應用就是如上所示,定義了一個 application 函數(callable object),callable object(可調用對象) 包括: 一個函數、方法、類或一個實現了__call__
的實例均可以用做應用程序對象。這個函數接受兩個參數,分別是environ和start_response。服務器
經過回調函數(start_response)將響應狀態和響應頭返回給 server,同時返回響應正文(response body),響應正文是可迭代的、幷包含了多個字符串。數據結構
werkzeug 提供了 python web WSGI 開發相關的功能:app
下面使用 Werkzeug 來實現一個簡單的WSGI應用:框架
from werkzeug.wrappers import Request, Response def application(environ, start_response): request = Request(environ) text = 'Hello %s!' % request.args.get('name', 'World') response = Response(text, mimetype='text/plain') return response(environ, start_response)
如上代碼所示,請求數據須要環境對象,Werkzeug容許你以一個輕鬆的方式訪問數據。響應對象是一個 WSGI 應用,提供了更好的方法來建立響應。函數
具體建立一個 WSGI 應用請查看文檔,後面會陸續提到Flask框架中使用到Werkzeug的數據結構。這裏貼一些官方文檔的例子,使用werkzeug建立一個web 應用:
import os import redis import urlparse from werkzeug.wrappers import Request, Response from werkzeug.routing import Map, Rule from werkzeug.exceptions import HTTPException, NotFound from werkzeug.wsgi import SharedDataMiddleware from werkzeug.utils import redirect from jinja2 import Environment, FileSystemLoader class Shortly(object): """ Shortly 是一個實際的 WSGI 應用,經過 __call__ 方法直接調 用 wsgi_app, 同時經過一個可選設置建立一箇中間件,將static文件夾暴露給用戶: """ def __init__(self, config): self.redis = redis.Redis(config['redis_host'], config['redis_port']) def dispatch_request(self, request): return Response('Hello World!') def wsgi_app(self, environ, start_response): request = Request(environ) response = self.dispatch_request(request) return response(environ, start_response) def __call__(self, environ, start_response): return self. wsgi_app(environ, start_response) def create_app(redis_host='localhost', redis_port=6379, with_static=True): app = Shortly({ 'redis_host': redis_host, 'redis_port': redis_port }) if with_static: app.wsgi_app = SharedDataMiddleware(app.wsgi_app, { '/static': os.path.join(os.path.dirname(__file__), 'static') }) return app if __name__ == '__main__': from werkzeug.serving import run_simple app = create_app() run_simple('127.0.0.1', 5000, app, use_debugger=True, use_reloader=True)
思路很簡單,咱們的 Shortly 是一個實際的 WSGI 應用。 __call__
方法直接調用 wsgi_app 。這樣作咱們能夠裝飾 wsgi_app 調用中間件,就像咱們在 create_app 函數中作的同樣。 wsgi_app 實際上建立了一個 Request 對象,以後經過 dispatch_request 調用 Request 對象而後給 WSGI 應用返回一個 Response 對象。正如你看到的:不管是建立 Shortly 類,仍是建立 Werkzeug Request 對象來執行 WSGI 接口。最終結果只是從 dispatch_request 方法返回另外一個 WSGI 應用。這部分解釋來源於官方文檔的中文版。
本文主要解釋了WSGI規範和Werkzeug(WSGI 工具集),以及如何實現一個符合WSGI規範的WSGI應用,最後使用Werkzeug 工具集中的相關模塊,快速實現了一個基於WSGI的簡單應用。