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