Python wsgiref 库入门:从零搭建 WSGI 服务器
本文深入解析 Python 内置库 wsgiref 的工作原理,通过 make_server 和 demo_app 源码剖析 WSGI 协议规范。详细演示了两种实现 WSGI 应用的方式:基于类的 __call__ 方法与 __iter__ 方法,帮助开发者理解 Web 服务器与应用程序的交互机制。
WSGI 协议核心机制
Web 服务器网关接口(WSGI)定义了 Python Web 服务器与应用程序之间的标准交互方式。其核心流程包含以下关键步骤:
- 浏览器发起请求,WSGI Server 接收并解析 HTTP 报文。
- Server 将请求参数封装为 environ 字典,并准备 start_response 回调函数。
- Server 调用后台 App(可调用对象),注入 environ 和 start_response。
- App 执行逻辑处理,调用 start_response 设置状态码与响应头。
- App 返回包含 HTTP 正文的可迭代对象(通常为字节列表)。
- Server 将响应数据封装后返回给浏览器。
本质上,WSGI Server 是一个监听特定端口的 TCP 服务器,负责协议解析与数据转发;而 WSGI App 必须是一个可调用对象,严格遵循协议约定。

使用 wsgiref 快速搭建服务
Python 标准库提供了 wsgiref 模块,主要用于开发测试。该模块基于 Socket Server 编写,默认情况下会将所有 URL 请求路由到 demo_app 进行处理。虽然它不适合直接用于生产环境,但非常适合理解 WSGI 的工作流程。
以下是使用 make_server 启动服务的示例代码:
# wsgiref是Python自带的内置库,它用来开发者对wsgi进行测试用的,不可以用在生产环境中
from wsgiref.simple_server import make_server, demo_app
# wsgi也是基于socket server编写
# 默认情况下会将所有url都传入demo_app进行处理,具体可参考demo_app源码
# app参数可以是任何可调用对象,但是内部处理需要参考demo_app源码,即environ处理、start_response调用、返回值类型
ws = make_server('127.0.0.1', 9999, demo_app)
# 启动服务
ws.serve_forever()深入理解 demo_app 源码
要自定义 WSGI 应用,必须理解 demo_app 的内部逻辑。它接收 environ 和 start_response,并返回一个可迭代的字节列表。以下是其核心实现:
def demo_app(environ,start_response):
from io import StringIO
stdout = StringIO()
print("Hello world!", file=stdout)
print(file=stdout)
# environ是一个字典,包含了所有请求信息
h = sorted(environ.items())
for k,v in h:
print(k,'=',repr(v), file=stdout)
# return之前需要调用start_response设置响应头信息
start_response("200 OK", [('Content-Type','text/plain; charset=utf-8')])
return [stdout.getvalue().encode("utf-8")] # 一个可迭代对象,元素为byte类型,元素内容依据start_response中指定的Content-Type来指定关键点在于:
1. 必须先调用 start_response 设置状态码和头部。
2. 返回值必须是可迭代对象,且元素为 byte 类型。
自定义 WSGI 应用的两种实现方式
除了使用 demo_app,开发者可以自定义类来实现 WSGI 应用。主要有两种模式:
方式一:实现 __init__ 和 __iter__ 方法
这种方式将 environ 和 start_response 保存在实例变量中,通过 __iter__ 方法生成响应数据。在 make_server 中,只需传入类名即可。
# 第一种方式:定义类的__init__和__iter__方法,前者用来接收和处理environ和start_response,后者生成一个可迭代对象
# make_server中app参数只需传入类名即可
class ApplicationClass:
def __init__(self, environ, start_response):
self.e = environ
self.sr = start_response
def __iter__(self):
from io import StringIO
stdout = StringIO()
print("Hello world!", file=stdout)
print(file=stdout)
h = sorted(self.e.items())
for k, v in h:
print(k, '=', repr(v), file=stdout)
self.sr("200 OK", [('Content-Type', 'text/plain', 'charset=utf-8')])
yield from [stdout.getvalue().encode("utf-8")]
# 第二种方式:定义__call__方法,接收和处理environ和start_response,并返回一个可迭代对象
# make_server中app参数需要传入类的实例
class ApplicationInstance:
def __call__(self, environ, start_response):
from io import StringIO
stdout = StringIO()
print("Hello world!", file=stdout)
print(file=stdout)
h = sorted(environ.items())
for k, v in h:
print(k, '=', repr(v), file=stdout)
start_response("200 OK", [('Content-Type', 'text/plain', 'charset=utf-8')])
return [stdout.getvalue().encode("utf-8")]方式二:实现 __call__ 方法
这种方式更符合常规面向对象编程习惯。类实例作为可调用对象,直接接收参数并返回结果。在 make_server 中,需要传入类的实例。
以上就是 Python wsgiref 库使用(WSGI基础入门)的详细内容,更多关于 Python Web 开发、WSGI 协议原理的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









