在Django、Flask、Bottle和所有其他 Python Web 框架之下,都有 Web 服务器网关接口,简称 WSGI。WSGI 之于 Python 就像 Servlet 之于 Java 一样——一种用于 Web 服务器的通用规范,它允许不同的 Web 服务器和应用程序框架基于通用 API 进行交互。然而,与大多数事情一样,Python 版本要简单得多。
WSGI 在PEP 3333中定义,如果您在此快速介绍之后需要更多信息,我鼓励您将其作为参考阅读。
本文将从应用程序开发人员的角度向您介绍 WSGI 规范,并向您展示如何直接使用 WSGI 来创建应用程序(如果您愿意的话)。
你的第一个 WSGI 应用
这是最基本的 Python Web 应用程序:
<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-python">def <span style="color:#82aaff">app</span><span style="color:#c792ea">(</span>environ<span style="color:#c792ea">,</span> start_fn<span style="color:#c792ea">)</span><span style="color:#c792ea">:</span>
start_fn<span style="color:#c792ea">(</span><span style="color:#c3e88d">'200 OK'</span><span style="color:#c792ea">,</span> <span style="color:#c792ea">[</span><span style="color:#c792ea">(</span><span style="color:#c3e88d">'Content-Type'</span><span style="color:#c792ea">,</span> <span style="color:#c3e88d">'text/plain'</span><span style="color:#c792ea">)</span><span style="color:#c792ea">]</span><span style="color:#c792ea">)</span>
return <span style="color:#c792ea">[</span><span style="color:#c3e88d">"Hello World!\n"</span><span style="color:#c792ea">]</span>
</code></span></span>
而已!整个文件。将它命名为 app.py 并在任何与 WSGI 兼容的服务器上运行它,您将获得一个带有 200 状态的 Hello World 响应。您可以为此使用 gunicorn;只需通过 pip( pip install gunicorn
) 安装它并使用gunicorn app:app
. 此命令告诉 gunicorn 从 app 模块中的 app 变量获取 WSGI 可调用对象。
现在,你应该很兴奋。运行应用程序只需 3 行?那一定是某种记录(除了 PHP,因为 mod_php 是作弊的)。我敢打赌,你只是想知道更多。
那么 WSGI 应用程序的基本部分是什么?
- WSGI 应用程序是 Python可调用的,例如函数、类或具有
__call__
方法的类实例 - 应用程序可调用必须接受两个参数:
environ
,它是一个包含请求数据的 Python 字典,以及start_fn
,它本身是可调用的。 - 应用程序必须
start_fn
使用两个参数调用:状态代码(作为字符串)和表示为 2 元组的标头列表。 - 应用程序返回一个包含响应正文中字节的可迭代对象,以方便的、可流式传输的块形式——在本例中,是一个仅包含
"Hello, World!"
. (如果app
是一个类,这可以在__iter__
方法中完成。)
举例来说,接下来的两个例子与第一个例子是等价的:
<span style="background-color:#292d3e"><span style="color:#bfc7d5"><code class="language-python">class <span style="color:#ffcb6b">app</span><span style="color:#c792ea">(</span><span style="color:#82aaff">object</span><span style="color:#c792ea">)</span><span style="color:#c792ea">:</span>
def <span style="color:#82aaff">__init__</span><span style="color:#c792ea">(</span>self<span style="color:#c792ea">,</span> environ<span style="color:#c792ea">,</span> start_fn<span style="color:#c792ea">)</span><span style="color:#c792ea">:</span>
self<span style="color:#c792ea">.</span>environ <span style="color:#89ddff">=</span> environ
self<span style="color:#c792ea">.</span>start_fn <span style="color:#89ddff">=</span> start_fn
def <span style="color:#82aaff">__iter__</span><span style="color:#c792ea">(</span>self<span style="color:#c792ea">)</span><span style="color:#c792ea">:</span>
self<span style="color:#c792ea">.</span>start_fn<span style="color:#c792ea">(</span><span style="color:#c3e88d">'200 OK'</span><span style="color:#c792ea">,</span> <span style="color:#c792ea">[&