Python Web 框架、WSGI 和 CGI​​ 如何组合在一起

Posted

技术标签:

【中文标题】Python Web 框架、WSGI 和 CGI​​ 如何组合在一起【英文标题】:How Python web frameworks, WSGI and CGI fit together 【发布时间】:2010-09-18 03:51:09 【问题描述】:

我有一个Bluehost 帐户,我可以在其中将 Python 脚本作为 CGI 运行。我想这是最简单的 CGI,因为要运行我必须在 .htaccess 中定义以下内容:

Options +ExecCGI
AddType text/html py
AddHandler cgi-script .py

现在,每当我查找使用 Python 进行 Web 编程时,我都会听到很多关于 WSGI 以及大多数框架如何使用它的信息。但我只是不明白这一切是如何组合在一起的,尤其是当我的 Web 服务器被提供(Apache 在主机的机器上运行)而不是我真正可以玩的东西时(除了定义 .htaccess 命令)。

WSGI、CGI 和框架是如何连接的?如果我想在我的基本 CGI 配置上运行 Web 框架(比如 web.py 或 CherryPy),我需要知道、安装和做什么?如何安装 WSGI 支持?

【问题讨论】:

【参考方案1】:

您可以以run WSGI over CGI as Pep333 demonstrates 为例。然而,每次有请求时,都会启动一个新的 Python 解释器,并且需要构建整个上下文(数据库连接等),这都需要时间。

如果您想运行 WSGI,最好的办法是让您的主机安装 mod_wsgi 并进行适当的配置以将控制权交给您的应用程序。

Flup 是另一种使用 WSGI 运行的方式,适用于任何可以说 FCGI、SCGI 或 AJP 的网络服务器。根据我的经验,只有 FCGI 真正有效,它可以通过 mod_fastcgi 在 Apache 中使用,或者如果您可以使用 mod_proxy_fcgi 运行单独的 Python 守护程序。

WSGI 是一个很像 CGI 的协议,它定义了一组 webserver 和 Python 代码如何交互的规则,它被定义为Pep333。这使得许多不同的网络服务器可以使用许多不同的框架和应用程序使用相同的应用程序协议成为可能。这是非常有益的,并且非常有用。

【讨论】:

在 CGI 上运行 WSGI 是什么“flup”? Flup 与方案有何联系?【参考方案2】:

我认为Florian's answer 回答了您关于“什么是 WSGI”的问题,特别是如果您阅读了the PEP。

关于你最后提出的问题:

WSGI、CGI、FastCGI 等都是网络服务器运行代码并传递生成的动态内容的协议。将此与静态 Web 服务进行比较,后者基本上将纯 HTML 文件按原样交付给客户端。

CGI、FastCGI 和 SCGI 与语言无关。您可以使用 Perl、Python、C、bash 等语言编写 CGI 脚本。 CGI 定义哪个 可执行文件将被调用,基于 URL,以及 如何 它将被调用:参数和环境。它还定义了在您的可执行文件完成后应如何将返回值传递回 Web 服务器。这些变化基本上是为了能够处理更多请求、减少延迟等而进行的优化;基本概念是一样的。

WSGI 仅适用于 Python。 定义了标准函数签名,而不是与语言无关的协议:

def simple_app(environ, start_response):
    """Simplest possible application object"""
    status = '200 OK'
    response_headers = [('Content-type','text/plain')]
    start_response(status, response_headers)
    return ['Hello world!\n']

这是一个完整的(如果有限的话)WSGI 应用程序。支持 WSGI 的 Web 服务器(例如带有 mod_wsgi 的 Apache)可以在请求到达时调用此函数。

之所以如此出色,是因为我们可以避免从 HTTP GET/POST 转换为 CGI 再转换为 Python 的麻烦步骤,然后再返回。这是一种更直接、更干净、更高效的链接。

如果一个请求只需要一个函数调用,它还可以让在 Web 服务器后面运行长时间运行的框架变得更加容易。对于普通 CGI,您必须为每个单独的请求 start your whole framework up。

要获得 WSGI 支持,您需要安装 WSGI 模块(如 mod_wsgi),或使用内置 WSGI 的 Web 服务器(如 CherryPy)。如果这些都不可行,您可以使用 PEP 中给出的 CGI-WSGI 桥。

【讨论】:

不让 WSGI 语言不可知是谁的愚蠢想法?那有什么意义呢?不妨将整个 Python 作为 Apache 模块发布。 @SalmanPK 我认为这只是一种权衡。当然,通过简单地以所选语言实现功能来制作与语言无关的协议并不容易(如果不是不可能的话)。【参考方案3】:

它是 Python 的一个简单抽象层,类似于 Java 的 Servlet 规范。虽然 CGI 非常低级,只是将内容转储到进程环境和标准输入/输出中,但上述两个规范将 http 请求和响应建模为语言中的构造。然而,我的印象是,在 Python 中,人们还没有完全确定事实上的实现,因此您需要混合使用参考实现和其他实用程序类型的库,这些库提供其他东西以及 WSGI 支持(例如 Paste)。当然我可能是错的,我是 Python 的新手。 “Web 脚本”社区正在从不同的方向(共享主机、CGI 遗留、特权分离问题)解决问题,而不是 Java 人开始的奢侈(在专用环境中运行单个企业容器以对抗静态编译和部署)代码)。

【讨论】:

【参考方案4】:

WSGI、CGI 和框架是如何连接的?

Apache 监听端口 80。它收到一个 HTTP 请求。它解析请求以找到响应方式。 Apache 有很多响应选择。一种响应方式是使用 CGI 运行脚本。另一种响应方式是简单地提供文件。

在 CGI 的情况下,Apache 准备一个环境并通过 CGI 协议调用脚本。这是标准的 Unix Fork/Exec 情况——CGI 子进程继承了一个操作系统环境,包括套接字和标准输出。 CGI 子进程写一个响应,返回给 Apache; Apache 将此响应发送到浏览器。

CGI 原始且令人讨厌。主要是因为它为每个请求分叉一个子进程,并且子进程必须退出或关闭 stdout 和 stderr 以表示响应结束。

WSGI 是一个基于 CGI 设计模式的接口。它不一定是 CGI——它不必为每个请求派生一个子进程。它可以是 CGI,但不一定是。

WSGI 在几个重要方面增加了 CGI 设计模式。它为您解析 HTTP 请求标头并将其添加到环境中。它将任何面向 POST 的输入作为环境中的类文件对象提供。它还为您提供了一个函数来制定响应,从而使您免于大量格式化细节。

如果我想在我的基本 CGI 配置上运行 Web 框架(例如 web.py 或cherrypy),我需要了解/安装/做什么?

回想一下,分叉一个子进程是昂贵的。有两种方法可以解决此问题。

    嵌入 mod_wsgimod_python 在 Apache 中嵌入 Python;没有进程被分叉。 Apache 直接运行 Django 应用程序。

    守护进程 mod_wsgimod_fastcgi 允许 Apache 使用 WSGI 协议与单独的守护进程(或“长期运行的进程”)进行交互。您启动长时间运行的 Django 进程,然后配置 Apache 的 mod_fastcgi 以与该进程通信。

请注意,mod_wsgi 可以在任一模式下工作:嵌入式或守护进程。

当您阅读 mod_fastcgi 时,您会看到 Django 使用 flup 根据 mod_fastcgi 提供的信息创建一个与 WSGI 兼容的接口。管道是这样工作的。

Apache -> mod_fastcgi -> FLUP (via FastCGI protocol) -> Django (via WSGI protocol)

Django 有几个“django.core.handlers”用于各种接口。

对于 mod_fastcgi,Django 提供了一个manage.py runfcgi,它集成了 FLUP 和处理程序。

对于 mod_wsgi,有一个核心处理程序。

如何安装 WSGI 支持?

按照这些说明进行操作。

https://code.google.com/archive/p/modwsgi/wikis/IntegrationWithDjango.wiki

背景见此

http://docs.djangoproject.com/en/dev/howto/deployment/#howto-deployment-index

【讨论】:

我无法安装 mod_wsgi,因为我在共享主机上。我只有 fcgi 支持。我怎样才能通过它运行 WSGI 应用程序? +1 这是一个很好的答案并回答了我想到的许多(但不是全部)问题。这个答案仍然不完整。您对 CGI 和 WSGI 进行了很好的解释,但 FASTCGI 和 WSGI 之间的关系和区别是什么?哪个更好?它们是如何工作的? mod_python 是如何出现的? S.Lott,与其抱怨人们问哪个“更好”,不如简单地说“mod_wsgi 作为 X 更好,fastcgi 对 Y 更好”,如果 OP 有更具体的问题,他们会问。 @Greg Lind:为什么不简单地说“mod_wsgi 比 X 好,fastcgi 比 Y 好”?因为这不是很容易做到的。有几十个非功能性质量因素是 X 和 Y 集合的元素。很难一一列举。对于人们来说,就相关的质量因素提出具体问题要好得多。 只是为了说明:runfcgi 选项自 1.7 版以来已弃用,并且在 Django 1.9 中删除了 FastCGI 支持。【参考方案5】:

如果你不清楚这个领域的所有术语,让我们面对它,它是一个令人困惑的首字母缩略词,还有一个很好的背景阅读器,它以官方 python HOWTO 的形式讨论 CGI 与 FastCGI 与。 WSGI等:http://docs.python.org/howto/webservers.html

【讨论】:

网址已过时,我认为这是更新的一个:docs.python.org/2.7/howto/webservers.html 很棒的材料 :) 人们应该阅读这个官方介绍以及接受的答案。

以上是关于Python Web 框架、WSGI 和 CGI​​ 如何组合在一起的主要内容,如果未能解决你的问题,请参考以下文章

多套方案来提高python web框架的并发处理能力

Web开发:常用框架

py web框架考察点

CGI FastCGI WSGI 解析

Web开发:CGI和WSGI

wsgi & cgi的一些概念解释