天天看點

Python Web 應用:WSGI基礎

在django,flask,bottle和其他一切python web 架構底層的是web server gateway interface,簡稱wsgi。wsgi對python來說就像 servlets對java一樣——一種用于web伺服器并允許不同web伺服器和應用架構基于通用api互動的通用規範。然而,對于大多數事情,python版本實作相當簡單。

wsgi被定義在pep 3333協定裡面,如果在讀完本文之後你想學到更多東西的話,作者建議讀者先閱讀一下簡介。

Python Web 應用:WSGI基礎

本文将從一個應用開發者的角度來向你介紹wsgi說明,并且向你展示怎樣直接通過wsgi來開發應用程式(如果你迫不及待的話)。

你的第一個wsgi應用

下面是最基本的python web應用:

就是這樣!整個檔案。先命名為app.py然後在任何wsgi可編譯伺服器上面運作,然後你就可以得到一個hello world并伴随一個200的響應狀态碼。你可以使用gunicorn來完成,通過pip(pip install gunicorn)來安裝并執行gunicorn app:app。這條指令告訴gunicorn從應用子產品裡的應用變量去擷取可調用的wsgi。

剛才,十分興奮吧。僅僅三行代碼就可以運作一個應用?那一定是某種意義上的記錄(不包括php,因為mod_php在起作用)。我敢打賭你現在一定想更加深入了解下去了。

是以一個wsgi應用最重要的部分是什麼呢?

一個wsgi應用是python可調用的,就像一個函數,一個類,或者一個有__call__方法的類執行個體

可調用的應用程式必須接受兩個參數:environ,一個包含必要資料的python字典,start_fn,它自己是可調用的。

應用程式必須能調用start_fn和兩個參數:狀态碼(字元串),和一個頭部以兩個元組表述的清單。

應用程式傳回一個在傳回體裡包含bytes的友善的可疊代對象,流式的部分——例如,一個個隻包含“hello,world!”字元串的清單。(如果app是一個類的話,可以在__iter__方法裡完成)

例如下面兩個例子和第一個是等價的:

你可能已經開始思考能用這些東西來做什麼了,但是最可能相關的一項是用來寫中間件。

讓它活躍起來

中間件是一種友善擴充wsgi應用功能性的方法。因為你隻需提供一個可調用的對象,你可以任意把它包裹在其他函數裡。

例如,假設我們想檢測一下environ裡面的内容。我們可以輕易地建立一個中間件來完成,如下所示:

這裡,log_environ是一個傳回函數的函數,它在environ參數延遲原始回調之前裝飾該參數。

這樣寫中間件的優點是中間件和處理器不需要知道或者關心對方。你可以輕易地綁定log_environ到一個flask應用上面,例如,因為flask應用是wsgi應用。

其他一些有用的中間件設計:

如果你不想讓你的檔案有一個很大的金字塔底的話,你可以使用reduce一次應用到多個中間件上。

利用start_fn參數的優點你也可以寫裝飾響應體的中間件。下面是一個内容類型頭部是text/plain反轉輸出結果的中間件。

由于start_fn和響應體的分離有一點混亂,但是還是完美運作的。

同時請注意,為了嚴格遵循wsgi規範,如果存在的話,我們必須在響應體裡檢查close方法并且調用它。wsgi應用程式有可能傳回一個write函數而不是一個調用處理器的可疊代對象,如果你想要你的中間件支援更早的應用的話,你可能需要處理這個問題。

一旦你開始一點點把玩原生wsgi,你就開始了解為什麼python有一堆web架構。wsgi讓從底層造一些東西變得十分簡單。例如,你也許正在考慮下面的路由問題:

如果你喜歡下面資源集合的靈活性的話,直接使用wsgi造輪子還是十分友善的。

模闆庫:投入任何你喜歡的模闆(例如,jinja2,pystashe)然後從你的處理器傳回渲染後的模闆!

用一個庫幫助你的路由,如routes或者werkzeug’s routing。實際上,如果你想輕松使用wsgi的話,看一看werkzeug吧。

使用任何flask或者相似的資料庫遷移庫。

當然,對于非專業的應用,你也可能想使用一下架構,那樣的話,一些特殊的諸如此類的例子也可以得到合了解決。

關于伺服器呢?

有許許多多服務wsgi應用的方法。我們已經讨論過gunicorn了,一個相當好的選擇。uwsgi是另外一個不錯的選擇。但是請確定在服務這些靜态東西之前設定好nginx一類的東西,并且你應該有一個固定的開始節點。