摘要:在介紹之前,先介紹一下,它為語言定義的服務(wù)器和應用程序或框架之間的一種簡單而通用的接口。這個函數(shù)接受兩個參數(shù),分別是和。響應對象是一個應用,提供了更好的方法來創(chuàng)建響應。這部分解釋來源于官方文檔的中文版。
Werkzeug 是一個WSGI工具包,也可以作為一個Web框架的底層庫。
WSGI在介紹Werkzeug之前,先介紹一下 WSGI(Python Web Server Gateway Interface),它為Python語言定義的Web服務(wù)器和Web應用程序或框架之間的一種簡單而通用的接口。這是一個規(guī)范,描述了web server如何與web application交互、web application如何處理請求,該規(guī)范的具體描述在PEP3333,強烈推薦先閱讀 PEP3333 再回頭來閱讀本文。
WSGI 分為兩個部分:
Server/Gateway: 即是HTTP Server, 負責從客戶端(Nginx、apache、IIS)接收請求,將 request 轉(zhuǎn)發(fā)給 application, 并將 application(可能是個Flask應用) 返回的response 返回給客戶端
Application/Framework: 一個python web 應用或 web 框架接收由 server 轉(zhuǎn)發(fā)的request,處理請求,并將處理結(jié)果返回給 server
可以通過下面兩張圖片來梳理一下它們之間的調(diào)用關(guān)系:
先從一份示例代碼理解:
def application(environ, start_response): start_response("200 OK", [("Content-Type", "text/plain")]) return ["Hello World!"]
一個最基本的 WSGI 應用就是如上所示,定義了一個 application 函數(shù)(callable object),callable object(可調(diào)用對象) 包括: 一個函數(shù)、方法、類或一個實現(xiàn)了__call__的實例都可以用作應用程序?qū)ο?。這個函數(shù)接受兩個參數(shù),分別是environ和start_response。
environ是一個字典包含了CGI中的環(huán)境變量
start_response也是一個callable,接受兩個必須的參數(shù),status(HTTP狀態(tài))和response_headers(響應消息的頭)
通過回調(diào)函數(shù)(start_response)將響應狀態(tài)和響應頭返回給 server,同時返回響應正文(response body),響應正文是可迭代的、并包含了多個字符串。
Werkzeugwerkzeug 提供了 python web WSGI 開發(fā)相關(guān)的功能:
路由處理:如何根據(jù)請求 URL 找到對應的視圖函數(shù)
request 和 response 封裝: 提供更好的方式處理request和生成response對象
自帶的 WSGI server: 測試環(huán)境運行WSGI應用
下面使用 Werkzeug 來實現(xiàn)一個簡單的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)
如上代碼所示,請求數(shù)據(jù)需要環(huán)境對象,Werkzeug允許你以一個輕松的方式訪問數(shù)據(jù)。響應對象是一個 WSGI 應用,提供了更好的方法來創(chuàng)建響應。
具體創(chuàng)建一個 WSGI 應用請查看文檔,后面會陸續(xù)提到Flask框架中使用到Werkzeug的數(shù)據(jù)結(jié)構(gòu)。這里貼一些官方文檔的例子,使用werkzeug創(chuàng)建一個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__ 方法直接調(diào) 用 wsgi_app, 同時通過一個可選設(shè)置創(chuàng)建一個中間件,將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__ 方法直接調(diào)用 wsgi_app 。這樣做我們可以裝飾 wsgi_app 調(diào)用中間件,就像我們在 create_app 函數(shù)中做的一樣。 wsgi_app 實際上創(chuàng)建了一個 Request 對象,之后通過 dispatch_request 調(diào)用 Request 對象然后給 WSGI 應用返回一個 Response 對象。正如你看到的:無論是創(chuàng)建 Shortly 類,還是創(chuàng)建 Werkzeug Request 對象來執(zhí)行 WSGI 接口。最終結(jié)果只是從 dispatch_request 方法返回另一個 WSGI 應用。這部分解釋來源于官方文檔的中文版。
總結(jié)本文主要解釋了WSGI規(guī)范和Werkzeug(WSGI 工具集),以及如何實現(xiàn)一個符合WSGI規(guī)范的WSGI應用,最后使用Werkzeug 工具集中的相關(guān)模塊,快速實現(xiàn)了一個基于WSGI的簡單應用。
參考Werkzeug 中文文檔
Werkzeug 英文文檔
WSGI Servers
WSGI協(xié)議的原理和實現(xiàn)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/42491.html
摘要:本文就主要針對一個應用的運行過程進行簡要分析,后續(xù)文章還會對框架的一些具體問題進行分析。所有的請求處理過程,都會在這個上下文對象中進行。和一些全局變量注意當進入這個上下文對象時,會觸發(fā)。 相信很多初學Flask的同學(包括我自己),在閱讀官方文檔或者Flask的學習資料時,對于它的認識是從以下的一段代碼開始的: from flask import Flask app = Flask(...
摘要:簡介官網(wǎng)上對它的定位是一個微開發(fā)框架。另外一個必須理解的概念是,簡單來說就是一套和框架應用之間的協(xié)議。功能比較豐富,支持解析自動防止攻擊繼承變量過濾器流程邏輯支持代碼邏輯集成等等。那么,從下一篇文章,我們就正式開始源碼之旅了 文章屬于作者原創(chuàng),原文發(fā)布在個人博客。 flask 簡介 Flask 官網(wǎng)上對它的定位是一個微 python web 開發(fā)框架。 Flask is a micro...
摘要:中有一個非常重要的概念每個應用都是一個可調(diào)用的對象。它規(guī)定了的接口,會調(diào)用,并傳給它兩個參數(shù)包含了請求的所有信息,是處理完之后需要調(diào)用的函數(shù),參數(shù)是狀態(tài)碼響應頭部還有錯誤信息。一般來說,嵌套的最后一層是業(yè)務(wù)應用,中間就是。 文章屬于作者原創(chuàng),原文發(fā)布在個人博客。 WSGI 所有的 python web 框架都要遵循 WSGI 協(xié)議,如果對 WSGI 不清楚,可以查看我之前的介紹文章。 ...
摘要:具體怎么實現(xiàn)的呢,思想其實特別簡單,我們在深入理解中的變量上一文的最后有提起過,就是創(chuàng)建一個全局字典,然后將線程或者協(xié)程標識符作為,相應線程或協(xié)程的局部數(shù)據(jù)作為。 在上篇我們看到了 ThreadLocal 變量的簡單使用,中篇對python中 ThreadLocal 的實現(xiàn)進行了分析,但故事還沒有結(jié)束。本篇我們一起來看下Werkzeug中ThreadLocal的設(shè)計。 Werkzeug...
閱讀 2189·2023-04-25 19:06
閱讀 1389·2021-11-17 09:33
閱讀 1777·2019-08-30 15:53
閱讀 2599·2019-08-30 14:20
閱讀 3554·2019-08-29 12:58
閱讀 3553·2019-08-26 13:27
閱讀 513·2019-08-26 12:23
閱讀 494·2019-08-26 12:22