所有的Python web框架都需要WSGI協(xié)議,所以要深入了解一個web框架,很有必要去了解下WSGI;
WSGI(Web Server Gateway Interface) 的任務(wù)就是把上面的數(shù)據(jù)在 http server 和 python 程序之間簡單友好地傳遞。它是一個標(biāo)準(zhǔn),被定義在PEP 333。需要 http server 和 python 程序都要遵守一定的規(guī)范,實現(xiàn)這個標(biāo)準(zhǔn)的約定內(nèi)容,才能正常工作。

image
圖片出處
WSGI Application端
application端定義非常簡單,它只要求開發(fā)者實現(xiàn)一個函數(shù)來響應(yīng)HTTP請求。
這個函數(shù)就是一個符合WSGI標(biāo)準(zhǔn)的一個HTTP處理函數(shù),它接收兩個參數(shù):
-
environ: 一個包含所有HTTP請求信息的dict對象。 -
start_response: 一個發(fā)送HTTP響應(yīng)的函數(shù),這個函數(shù)接受兩個參數(shù),一個是HTTP響應(yīng)碼,一個是HTTP header。
# wsgi_client.py
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return ["hello world"]
WSGI Server端
envrion和start_response這兩個參數(shù)由服務(wù)端提供,PEP333里給出了一個wsgi server的簡單實現(xiàn):
import os, sys
def run_with_cgi(application): # application 是程序端的可調(diào)用對象
# 準(zhǔn)備 environ 參數(shù),這是一個字典,里面的內(nèi)容是一次 HTTP 請求的環(huán)境變量
environ = dict(os.environ.items())
environ['wsgi.input'] = sys.stdin
environ['wsgi.errors'] = sys.stderr
environ['wsgi.version'] = (1, 0)
environ['wsgi.multithread'] = False
environ['wsgi.multiprocess'] = True
environ['wsgi.run_once'] = True
environ['wsgi.url_scheme'] = 'http'
headers_set = []
headers_sent = []
# 把應(yīng)答的結(jié)果輸出到終端
def write(data):
sys.stdout.write(data)
sys.stdout.flush()
# 實現(xiàn) start_response 函數(shù),根據(jù)程序端傳過來的 status 和 response_headers 參數(shù),
# 設(shè)置狀態(tài)和頭部
def start_response(status, response_headers, exc_info=None):
headers_set[:] = [status, response_headers]
return write
# 調(diào)用客戶端的可調(diào)用對象,把準(zhǔn)備好的參數(shù)傳遞過去
result = application(environ, start_response)
# 處理得到的結(jié)果,這里簡單地把結(jié)果輸出到標(biāo)準(zhǔn)輸出。
try:
for data in result:
if data: # don't send headers until body appears
write(data)
finally:
if hasattr(result, 'close'):
result.close()
或者,python中也內(nèi)置了一個WSGI服務(wù)器模塊wsgiref, 通過這個模塊就可以快速實現(xiàn)了個WSGI Server來測試我們的application:
# wsgi_server.py
# 從wsgiref模塊導(dǎo)入:
from wsgiref.simple_server import make_server
# 導(dǎo)入我們自己編寫的application函數(shù):
import wsgi_client
# 創(chuàng)建一個服務(wù)器,IP地址為空,端口是8000,處理函數(shù)是application:
httpd = make_server('', 8000, wsgi_client.application)
print('Serving HTTP on port 8000...')
# 開始監(jiān)聽HTTP請求:
httpd.serve_forever()
可以看到結(jié)果為wsgi_client.py中定義的hello world

200ok.png
Flask框架中的一個核心庫werkzeug其實就是Python的WSGI規(guī)范的實用函數(shù)庫