WSGI,或者 Web Server Gateway Interface,是 Python 中用于在 Web 服務器和 Web 應用之間進行通信的標準接口。WSGI 不僅定義了 Web 服務器怎么與 Web 應用交互,也定義了 Web 應用程序如何處理 HTTP 請求。
基本的 WSGI 接口定義了兩個方面:
服務器或網關端:這一側會將接受的 HTTP 請求轉化為 WSGI 格式并發送給應用程序。
應用程序端:Web 應用會接受 WSGI 請求并返回 HTTP 響應。
一個簡單的 WSGI 程序示例:
python
Copy code
def simple_app(environ, start_response):
status = '200 OK'
headers = [('Content-type', 'text/plain')]
start_response(status, headers)
return ["Hello WSGI World!\n"]
if __name__ == '__main__':
from wsgiref.simple_server import make_server
httpd = make_server('', 8000, simple_app)
print("Serving on port 8000...")
httpd.serve_forever()
在這個例子中,simple_app 是 WSGI 應用,它接受兩個參數:environ 和 start_response。environ 是一個包含所有 HTTP 請求信息的字典,start_response 是一個用于發送 HTTP 響應的回調函數。
此代碼使用 wsgiref 來創建一個 WSGI HTTP 服務器,它監聽8000端口,等待 HTTP 請求并把請求傳遞給 simple_app WSGI 應用處理。
WSGI 已經廣泛應用在各類 Python Web 框架中,例如 Flask、Django 等。通過 WSGI,Python 的 Web 應用可以與各種不同的 Web 服務器(如 Apache,Nginx 等)進行通信
##
WSGI是 Python 用于 Web 服務器和 Web 應用程序間通信的標準化的接口定義。它存在的目的是為了使得更換 Web 服務器或 Web 框架變得更為簡單,因為借助 WSGI,它們都遵循了相同的規范以實現相互的通信。
基于 WSGI 的應用需要實現一個簡單的調用接口,這個接口接受兩個參數:"環境"(environ)(一個包含了 WSGI/CGI 環境變量的字典)和 "開始響應"(start_response)(一個用來啟動響應過程的回調函數)。這個函數需要返回一個可迭代的對象,這個對象將被用于作為 HTTP 響應的體。
一個最基本的實現一個 WSGI 應用的例子是這樣的:
python
Copy code
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return [b"Hello World!"] # 返回一個 byte 字符串
這個例子接受 HTTP 請求,并返回 "Hello World!" 的 HTTP 響應。
WSGI 使得 Python 可以更方便地開發 Web 應用,允許開發者可以使用各種不同的 Web 服務器(例如 Apache,Nginx,Gunicorn 等)以及各種不同的 Web 框架(例如 Django,Flask,Pyramid 等)。所有支持 WSGI 的應用在所有支持 WSGI 的服務器上的工作方式是相同的。這為 Python Web 開發提供了很大的靈活性。
## Sample
```
def simple_app(environ, start_response):
status = '200 OK'
headers = [('Content-type', 'text/plain')]
start_response(status, headers)
return ["Hello WSGI World!\n".encode()]
if __name__ == '__main__':
from wsgiref.simple_server import make_server
httpd = make_server('', 8000, simple_app)
print("Serving on port 8000...")
httpd.serve_forever()
```
## 問題
```
Traceback (most recent call last):
File "C:\inssoftware\Python\Python311\Lib\wsgiref\handlers.py", line 138, in run
self.finish_response()
File "C:\inssoftware\Python\Python311\Lib\wsgiref\handlers.py", line 184, in finish_response
self.write(data)
File "C:\inssoftware\Python\Python311\Lib\wsgiref\handlers.py", line 278, in write
assert type(data) is bytes, \
```
WSGI 應用返回的數據類型應該是字節(bytes),而不是其他類型。WSGI 規范規定,WSGI 應用的返回值必須是字節流(也就是 bytes 類型的數據),如果你嘗試返回一個字符串(str 類型的數據),就會收到這個錯誤。
在你的代碼中,確保你的 WSGI 應用返回一個字節流。在 Python 中,可以使用字符串的 encode() 方法來將其轉變成字節流:
python
Copy code
def simple_app(environ, start_response):
status = '200 OK'
headers = [('Content-type', 'text/plain')]
start_response(status, headers)
return ["Hello WSGI World!\n".encode()] # encode the string to bytes
if __name__ == '__main__':
from wsgiref.simple_server import make_server
httpd = make_server('', 8000, simple_app)
print("Serving on port 8000...")
httpd.serve_forever()
在這個修改后的例子中,返回的字符串 "Hello WSGI World!\n" 被通過 .encode() 方法轉變為了字節流,因此不會再觸發上述的錯誤。
## 不符合WSGI標準
Python 的 WSGI(Web Server Gateway Interface)規定了一套標準,定義了 Web 服務器(或者說是網關)如何與 Python Web 應用之間進行通信。如果一個應用或服務器不能滿足這個規范,我們就通常會說它不符合 WSGI 標準。
一些不符合 WSGI 標準的例子可能包括:
無法適配WASGI環境和回調函數的應用:一個 WSGI 應用必須是一個可調用的 Python 對象(最常見的是一個函數或者一個類的實例),它需要接受兩個參數:一個包含了所有 WSGI 和 CGI 環境變量的字典,和一個用來開始響應過程的回調函數。如果一個應用無法滿足這個要求,那它就不是一個 WSGI 應用。
python
Copy code
def application(environ, start_response):
#...
返回類型不正確的應用:WSGI 應用需要返回一個響應主體(body),這個主體必須是一個可以返回字節串的可迭代對象。如果返回的對象無法迭代,或者迭代出來的不是字節串,那這個應用就不符合 WSGI 規范。
python
Copy code
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return [b"Hello World!"] # 返回一個 byte 字符串
不兼容錯誤流的應用:WSGI 規定了 WSGI 應用需要可以寫入到 wsgi.errors 流。如果無法做到這一點,那此應用就不符合 WSGI 規范。
以上這些都只是一些例子,實際上,有許多其他的可能會導致一個應用或者服務器不符合 WSGI 規范。為了確保兼容性,你應當參照 PEP 3333(這是 WSGI 規范的官方定義)創建你的應用,或是使用兼容 WSGI 規范的 Web 框架(比如 Flask,Django 等)。
- 前言
- 1.入門篇
- Python介紹
- 安裝與使用
- Python開發利器之VS Code
- 模塊安裝
- 命令行
- 一次Python無法安裝模塊的問題探索與解決之旅
- 命令運行
- Conda
- 下載地址
- 2.基礎篇
- 基礎語法
- 輸入與輸出
- with as的用法
- 注釋
- Python命令行參數
- 編碼
- 變量類型
- 列表遍歷
- 運算符
- 表達式語句
- 條件
- 循環
- 日期和時間
- 函數
- 高級語法
- @符號-裝飾器
- 模塊和包
- name
- init.py
- 錯誤和異常
- 面向對象
- 3.專題篇
- 常用功能
- Python 字符串連接
- python web
- Python CGI編程
- Python OAuth2
- 認證 Flask-HTTPAuth
- 常用命令
- 內置函數
- dir()
- print(f)
- 標準模塊
- sys
- pickle-數據序列化
- os
- IO(輸入輸出)
- 鍵盤輸入
- 文件讀寫
- 測試
- Python測試框架之pytest快速入門
- pytest-bdd快速示例和問題解決
- 基于pytest-bdd的項目目錄結構和命名規范
- python BDD 的相關概念
- Behave介紹和快速示例
- Python BDD之Behave測試報告
- Python BDD 框架比較之 pytest-bdd vs behave
- pytest進階
- Flask + pytest測試
- 參考網址
- pytest-bdd進階
- hehave進階
- 測試路徑
- python + selunium
- HTML 根據多層CSS 查找元素
- 等待執行
- 使用text 查找 span
- pytest如何在控制臺輸出
- 4.問題篇
- pip pip3 及區別
- TypeError: can only concatenate str (not "NoneType") to str
- 5.實戰篇
- matplotlib-繪圖包
- 導入類
- 命名規范
- 模塊查找
- 6.進階篇
- Flask
- Flask介紹
- Flask擴展模塊
- Flask-Login
- 問題
- Jinja2
- Flask-RESTful
- Flask-JWT-Extended
- WSGI
- Flask-SQLAlchemy
- 部署
- Flask VS Django
- Flask Web
- Flask + Vue
- Flask實戰
- Flask 標準目錄結構
- Blueprints
- 參考
- FastAPI 測試
- https 證書 Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate