0%

PEP3333 (Part 1) -- 为什么需要 WSGI

译者的话

PEP3333 的前身是一个重要的规范 PEP333,一个关于 WSGI 标准的规范,现代 Python 的 Web 开发的深入几乎都不可能绕开这一个标准。译者当初接触到类似的一个概念是 ASP.NET Web API v2 中提出来的 OWIN。两者的定义和概念都有不少的相似之处,但背景却是大不相同:Python 是为了解决当时五花八门的服务器以及 Web 框架之间耦合度强导致的各种不兼容问题;而 .NET 提出这个是为了给开源铺路,摆脱 ASP.NET 对于 IIS 的强依赖性。不过殊途同归,标准的提出,都是为了方便真正的使用者:Web 开发人员。

本文是一篇译文,鉴于本人略捉急的英语水平,思考再三还是觉得把我的翻译放出来,一来是可以方便查阅,另一方面也希望点进来的各位可以提出修改的意见。

针对 PEP 333 读者的序言

这是 PEP 333 的更新版本,稍微修改了以提高在 Python3 下的可读性,并包含了几个事实上 WSGI 协议的长期修正(它的示例代码也已被移植到 Python3 当中)。

由于程序上的原因,这必须是一个和 PEP333 具有明显区别性的 PEP,但它没有对那些使用 Python 2.x 编写的向前兼容的服务器程序或者应用程序做任何改变,也就是说,如果你的 2.x 的服务器程序或者应用程序是兼容 PEP333 的,那么它也会兼容 PEP3333.

然而,在 Python3 的环境下,你的应用程序或者服务器程序必须遵守以下下列标题所罗列的规则,包括字符串类型以及 Unicode 编码等的问题。

如果想知道这份文档和 PEP 333 的逐行差异,你可能需要查看 SVN 修订历史,从 84854 版本往前。

摘要

该文档指定了一个在 Web 服务器程序和 Python Web 应用程序或应用框架之间的推荐标准接口,以促进 Web 应用程序在各种 Web 服务器程序上的可移植性。

原来的基本原理以及实现目标(来自 PEP 333)

Python 目前拥有各种各样的 Web 应用框架,比如 Zope、Quixote、Webware、SkunkWeb、PSO 以及 Twisted Web —— 太多了,这里仅列举这几个。对 Python 用户来说,这样广泛的选择会导致一个问题:因为一般而言,他们对于 Web 框架的选择受限于它们(这些框架)可用于托管的服务器程序,反之亦然。

相比之下,虽然 Java 也拥有大量的 Web 应用程序框架,但 Java 的 Servlet API 使得任何使用 Java Web 应用框架编写的 Web 程序可以运行在任何一个支持 Servlet API 的 web 服务器上。

对于使用 Python 的服务器程序 —— 无论这些服务器是用 Python 编写的(如 Medusa)、还是用嵌入式 Python 编写的(如 mod_python)、或者是通过网关协议调用 Python 的(如 GCI、FastCGI 等等),如果有像这样一个可广泛使用的 API 接口,来分离框架和 Web 服务器两者的选择,会给到用户更多自由去组合他们的选择,那样他们就可以专注于他们的擅长的领域(避免提高学习成本)。

因此,这个 PEP 旨在提供一个在 Web 服务器以及 Web 应用或框架之间通用的接口:Python Web 服务器网关接口(Python Web Server Gateway Interface,Python WSGI)。

但是 WSGI 规范的存在对于现有的 Python web 应用的服务器以及框架毫无作用。服务器的维护人或组织以及框架的作者必须实现 WSGI 标准才能起到效果。

然而,由于没有现存的服务器或者框架,因此对于那些实现了 WSGI 支持的作者们其实不会有什么立竿见影的效果。因此,WSGI 必须易于实现,以便作者在初始投入成本足够低。

然而,服务器以及框架层面接口的易实现性对于 WSGI 接口的实用性目的至关重要,因此这是任何设计决策的重要判断准则。

然而要注意的是,易于实现这回事,对于框架开发者和 Web 应用开发者是不一样的。WSGI 对于框架作者来说是一个纯粹“无装饰”(no frills)的接口,因为像响应对象(response object)和 cookie 处理之类的 “圣诞树装饰”(bells and whistles)会妨碍现有框架内对这些问题的处理。重申一次, WSGI 的目标是是实现现有服务器和应用(或框架)的简单互连,而不是创建一个新的 Web 框架。

还要注意的是,这个目标也制约了 WSGI 接口想从已经部署的 Python 版本上索取任何东西的想法,因为这个标准并没有提供或要求使用新的的标准库,而且 WSGI 除了需要 Python2.2.2 以上也没有要求别的东西(但是,对于未来的 Python 版本来说,在标准库中提供的服务器中包含对该接口的支持将是一个更好的主意)。

除了对于现有以及未来的框架和服务器易于实现之外,它同样要易于创建请求预处理器(request preprocessor)、响应后续处理器(response postprocessor)、以及其他基于 WSGI 的“中间件”组件,这些组件对于承载它们的服务器看起来像一个应用,对于它们承载的应用又看上去像个服务器。

如果中间件可以既简单又健壮,那么 WSGI 就可以在服务器和框架中广泛使用,有可能它就催生一种全新的 Python Web 框架:一种全部又 WSGI 中间件组件组成的松耦合框架。实际上,现有的框架的作者甚至可以采用这种方式去重构它们框架提供的服务(译者:如路由、过滤器、模板引擎等),这个做法将会使得这一切会变得更像一个个使用了 WSGI 的库而不是一个独立的框架。这将允许应用开发者为特定的功能点选择“最佳拍档”的组件组合,而不是寄希望于单一框架的优缺点权衡。

当然,这一天对于这篇文章的诞生日而言无疑是相当遥远的。同时,对于 WSGI 接口来说,能在任何服务器和任何框架上被实现是一个可以期待的短期目标。

最后,需要提一点,当前的 WSGI 版本并没有规定任何特定的机制来“部署”一个使用了 Web 服务器或者服务网关(server gateway)的应用程序。目前,这必须是由服务器或者网关来定义实现的。在足够多的服务器和框架都实现了 WSGI 接口之后,提供了不同部署方式的使用体验后,这可能会有另外一个新的 PEP,去描述 WSGI 服务器和应用框架的部署标准。