在用Python Web開發時常常會遇到WSGI,因此WSGI究竟是什麼呢?本文咱們一塊兒來揭開WSGI神祕的面紗!html
先來看一下WSGI的介紹:前端
全稱Python Web Server Gateway Interface,指定了web服務器和Python web應用或web框架之間的標準接口,以提升web應用在一系列web服務器間的移植性。 具體可查看 官方文檔python
從以上介紹咱們能夠看出:web
你可能會問,爲何須要WSGI?瀏覽器
首先,咱們明確一下web應用處理請求的具體流程:服務器
能夠看到,請求時Web服務器須要和web應用程序進行通訊,可是web服務器有不少種啊,Python web應用開發框架也對應多種啊,因此WSGI應運而生,定義了一套通訊標準。試想一下,若是不統一標準的話,就會存在Web框架和Web服務器數據沒法匹配的狀況,那麼開發就會受到限制,這顯然不合理的。app
既然定義了標準,那麼WSGI的標準或規範是?框架
web服務器在將請求轉交給web應用程序以前,須要先將http報文轉換爲WSGI規定的格式。函數
WSGI規定,Web程序必須有一個可調用對象,且該可調用對象接收兩個參數,返回一個可迭代對象:工具
經過以上學習,一塊兒實現一個簡單WSGI服務吧
首先,咱們編寫一個符合WSGI標準的一個http處理函數:
def hello(environ, start_response): status = "200 OK" response_headers = [('Content-Type', 'text/html')] start_response(status, response_headers) path = environ['PATH_INFO'][1:] or 'hello' return [b'<h1> %s </h1>' % path.encode()]
該方法負責獲取environ字典中的path_info,也就是獲取請求路徑,而後在前端展現。
接下來,咱們須要一個服務器啓動WSGI服務器用來處理驗證,使用Python內置的WSGI服務器模塊wsgiref,編寫server.py:
# coding:utf-8 """ desc: WSGI服務器實現 """ from wsgiref.simple_server import make_server from learn_wsgi.client import hello def main(): server = make_server('localhost', 8001, hello) print('Serving HTTP on port 8001...') server.serve_forever() if __name__ == '__main__': main()
執行python server.py,瀏覽器打開"http://localhost:8001/a",便可驗證。
經過實現一個簡單的WSGI服務,咱們能夠看到:經過environ能夠獲取http請求的全部信息,http響應的數據均可以經過start_response加上函數的返回值做爲body。
固然,以上只是一個簡單的案例,那麼在python的Web框架內部是如何遵循WSGI規範的呢?以Flask舉例,
Flask與WSGI
Flask中的程序實例app就是一個可調用對象,咱們建立app實例時所調用的Flask類實現了__call__方法,__call__方法調用了wsgi_app()方法,該方法完成了請求和響應的處理,WSGI服務器經過調用該方法傳入請求數據,獲取返回數據:
def wsgi_app(self, environ, start_response): ctx = self.request_context(environ) error = None try: try: ctx.push() response = self.full_dispatch_request() except Exception as e: error = e response = self.handle_exception(e) except: # noqa: B001 error = sys.exc_info()[1] raise return response(environ, start_response) finally: if self.should_ignore_error(error): error = None ctx.auto_pop(error) def __call__(self, environ, start_response): return self.wsgi_app(environ, start_response)
Flask的werkzeug庫是一個很是優秀的WSGI工具庫,具體的實現咱們以後再詳細學習。
以上。