Python WSGI 規(guī)范簡介
作為 Python Web 開發(fā)者來說,在開發(fā)程序階段一般是不會接觸到 WSGI 這個名詞的,但當程序開發(fā)完成,考慮上線部署的時候,WSGI 規(guī)范是一個繞不開的話題,本文將介紹何為 WSGI。
WSGI 全拼 Web Server Gateway Interface,是為 Python 語言定義的 Web 服務(wù)器和 Web 應用程序(或框架)之間的一種通用編程接口。翻譯成白話就是說 WSGI 是一個協(xié)議,就像 HTTP 協(xié)議定義了客戶端和服務(wù)端數(shù)據(jù)傳輸?shù)囊?guī)范,WSGI 協(xié)議定義了 Web 服務(wù)器和 Web 應用程序之間協(xié)同工作的規(guī)范。
Python Web 應用部署方案
Flask 或 Django 等 Web 框架都提供了內(nèi)置的 Web Server,本地開發(fā)階段可以使用 flask run 或 python manage.py runserver 來分別啟動 Flask 或 Django 內(nèi)置的 Server。
在生產(chǎn)環(huán)境部署應用時,通常不會使用框架內(nèi)置的 Server,而是使用 Gunicorn 或 uWSGI 來部署,以獲得更好的性能。部署過 Python Web 應用的同學應該對如下部署架構(gòu)有所了解,左側(cè)是瀏覽器,右側(cè)是服務(wù)器。在服務(wù)器內(nèi)部,首先通過 Nginx 來監(jiān)聽 80/443 端口,當接收到來自客戶端的請求時,Nginx 會將請求轉(zhuǎn)發(fā)到監(jiān)聽 5000 端口的 Gunicorn/uWSGI Server,接著請求會通過 WSGI 協(xié)議被傳遞到 Flask/Django 框架,在框架內(nèi)部處理請求邏輯后,會將響應信息按照原路返回。

你可能會問,Nginx 性能很高,為什么不將應用直接部署到 Nginx 上,而是中間通過 Gunicorn/uWSGI 做一層轉(zhuǎn)發(fā)呢?因為 Nginx 沒有遵循 WSGI 規(guī)范,并不能像 Gunicorn/uWSGI 這樣很容易的與 Flask/Django 框架結(jié)合起來。
WSGI 規(guī)范
根據(jù) Python Web 應用部署架構(gòu),我們知道了 WSGI 所處的位置,接下來看下 WSGI 規(guī)范具體定義了哪些內(nèi)容。
如同 HTTP 協(xié)議有一個客戶端和一個服務(wù)端,WSGI 協(xié)議有一個 Application 端和一個 Server 端,其中 Application 就是指 Flask、Django 這些 Web 框架,而 Server 就是指 Gunicorn、uWSGI 等 Web 服務(wù)器。
WSGI 協(xié)議規(guī)定 Application 端需要實現(xiàn)成一個可調(diào)用對象(函數(shù)、類等),其接口如下:
def simple_app(environ, start_response):
status = '200 OK'
response_headers = [('Content-type', 'text/plain')]
start_response(status, response_headers)
return ['Hello world!\n']
simple_app 就是一個最簡單的 Application,它需要接收兩個參數(shù),environ 是一個 dict,其中保存了所有 HTTP 請求相關(guān)的信息,由 Server 端提供,start_response 是一個可調(diào)用對象,同樣由 Server 端提供,simple_app內(nèi)部需要調(diào)用一次 start_response,并將 狀態(tài)碼 和 響應頭 當作參數(shù)傳遞給它,simple_app 最終會返回一個可迭代對象作為 HTTP Body 內(nèi)容返回給客戶端。
我們已經(jīng)知道了 Application 端接口,接下來看下一個符合 WSGI 協(xié)議的 Server 端實現(xiàn):
import os
def wsgi_server(application):
environ = dict(os.environ.items())
def start_response(status, response_headers):
print(f'status: {status}')
print(f'response_headers: {response_headers}')
result = application(environ, start_response)
for data in result:
print(f'response_body: {data}')
示例中 Server 端同樣使用函數(shù)來實現(xiàn),wsgi_server 接收一個 application 作為參數(shù),在其內(nèi)部構(gòu)造了 environ 和 start_response 兩個對象,這里使用環(huán)境變量信息來模擬 HTTP 請求信息構(gòu)造 environ 字典,start_response 同樣被定義為一個函數(shù),供 application 在內(nèi)部對其進行調(diào)用,wsgi_server 函數(shù)最后會調(diào)用 application 并對其進行打印。
現(xiàn)在有了 Application 端和 Server 端,我們可以來測試一下這個簡單的 WSGI 程序示例。只需要將 simple_app 作為參數(shù)傳遞給 wsgi_server 并調(diào)用 wsgi_server 即可:
wsgi_server(simple_app)
執(zhí)行以上代碼,將得到如下打?。?/p>
status: 200 OK
response_headers: [('Content-type', 'text/plain')]
response_body: Hello world!
以上,我們分別實現(xiàn)了符合 WSGI 規(guī)范的 Application 端和 Server 端,雖然程序看起來比較簡陋,但不論多么復雜的 Python Web 框架和 Server 都同樣遵循此規(guī)范。
WSGI 實際應用
學習了 WSGI 規(guī)范,我們可以來驗證下平時使用的 Python Web 框架是否真的遵循此規(guī)范,這里以 Flask 框架源碼為例,可以在 https://github.com/pallets/flask/blob/master/src/flask/app.py 查看 Flask 的定義:
class Flask(Scaffold):
...
def __call__(self, environ, start_response):
"""The WSGI server calls the Flask application object as the
WSGI application. This calls :meth:`wsgi_app`, which can be
wrapped to apply middleware.
"""
return self.wsgi_app(environ, start_response)
Flask 類內(nèi)部通過實現(xiàn) __call__ 方法,使得 Flask 實例對象成為一個可調(diào)用對象,其接口實現(xiàn)同樣符合 WSGI Application 規(guī)范。
以上就是Python WSGI 規(guī)范簡介的詳細內(nèi)容,更多關(guān)于Python WSGI 規(guī)范的資料請關(guān)注腳本之家其它相關(guān)文章!
- Python?Web開發(fā)通信協(xié)議WSGI?uWSGI?uwsgi使用對比全面介紹
- Python安裝和配置uWSGI的詳細過程
- 通過Python中的CGI接口講解什么是WSGI
- django生產(chǎn)環(huán)境搭建(uWSGI+django+nginx+python+MySQL)
- 淺析Python 中的 WSGI 接口和 WSGI 服務(wù)的運行
- Docker構(gòu)建python Flask+ nginx+uwsgi容器
- python web框架 django wsgi原理解析
- Python開發(fā)之Nginx+uWSGI+virtualenv多項目部署教程
- Python從wsgi導入失敗的問題解決方法
相關(guān)文章
python開發(fā)準備工作之配置虛擬環(huán)境(非常重要)
這篇文章主要介紹了python開發(fā)準備工作之配置虛擬環(huán)境(非常重要),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-02-02
python-nmap實現(xiàn)python利用nmap進行掃描分析
Nmap是一個非常用的網(wǎng)絡(luò)/端口掃描工具,如果想將nmap集成進你的工具里,可以使用python-nmap這個python庫,它提供了一個簡單的接口來使用nmap進行掃描,下面我們來看看python-nmap的具體應用吧2024-12-12
python實現(xiàn)去除下載電影和電視劇文件名中的多余字符的方法
這篇文章主要介紹了python實現(xiàn)去除下載電影和電視劇文件名中的多余字符的方法,可以批量修改視頻文件名稱,非常具有實用價值,需要的朋友可以參考下2014-09-09
探索Python fcntl模塊文件鎖和文件控制的強大工具使用實例
這篇文章主要介紹了Python fcntl模塊文件鎖和文件控制的強大工具使用實例探索,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2024-01-01
基于Django框架利用Ajax實現(xiàn)點贊功能實例代碼
點贊這個功能是我們現(xiàn)在經(jīng)常會遇到的一個功能,下面這篇文章主要給大家介紹了關(guān)于基于Django框架利用Ajax實現(xiàn)點贊功能的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧2018-08-08

