Python Web框架、WSGI和CGI如何结合在一起
我有一个Bluehost的账户,可以在上面运行Python脚本,使用的是CGI技术。我觉得这算是最简单的CGI,因为要运行这些脚本,我需要在.htaccess
文件中定义一些内容:
Options +ExecCGI
AddType text/html py
AddHandler cgi-script .py
现在,每当我查找关于用Python进行网页编程的信息时,听到很多关于WSGI的讨论,很多框架都在用它。但我就是搞不清楚这些东西是怎么联系在一起的,尤其是我的网页服务器是固定的(在主机上运行的Apache),我并不能随意更改它(除了定义.htaccess
中的命令)。
WSGI、CGI和各种框架之间是怎么关联的呢?如果我想在我的基本CGI配置上运行一个网页框架(比如web.py或CherryPy),我需要知道、安装和做些什么?如何安装WSGI支持呢?
5 个回答
你可以通过WSGI在CGI上运行,就像Pep333所示的那样。不过,每次有请求时,都会启动一个新的Python解释器,这样就需要重新建立整个环境(比如数据库连接等),这会耗费时间。
如果你想运行WSGI,最好的办法是让你的主机安装mod_wsgi,并进行适当的配置,以便将控制权交给你的应用程序。
Flup是另一种在支持FCGI、SCGI或AJP的任何网络服务器上运行WSGI的方法。根据我的经验,只有FCGI真正有效,它可以通过mod_fastcgi在Apache中使用,或者如果你能运行一个独立的Python守护进程,可以使用mod_proxy_fcgi。
WSGI是一种协议,类似于CGI,它定义了一套规则,说明网络服务器和Python代码如何互动,这些规则在Pep333中有详细说明。它使得许多不同的网络服务器可以使用许多不同的框架和应用程序,而不需要改变应用协议。这非常有利,使得WSGI变得非常有用。
我觉得Florian的回答很好地解释了你提到的“什么是WSGI”,特别是如果你去看看这个PEP文档
。至于你在最后提到的问题:
WSGI、CGI、FastCGI等都是一些协议,用于让网络服务器运行代码,并提供生成的动态内容。可以把它们和静态网页服务对比,静态网页服务就是把一个普通的HTML文件直接发给用户。
CGI、FastCGI和SCGI是与编程语言无关的。你可以用Perl、Python、C、bash等语言来写CGI脚本。CGI定义了哪个可执行文件会被调用,这个是根据URL来决定的,同时也定义了如何调用它:包括参数和环境。它还规定了当你的可执行文件完成后,返回值应该如何传回给网络服务器。这些变种基本上是为了优化,能够处理更多请求,减少延迟等等;基本概念是一样的。
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的网络服务器(比如带有mod_wsgi的Apache)可以在每次收到请求时调用这个函数。
这样做的好处是,我们可以避免从HTTP GET/POST转换到CGI再到Python,然后再返回的复杂步骤。这个过程更直接、更干净,也更高效。
而且,如果处理请求只需要调用一个函数,那么在网络服务器后面运行长时间的框架会变得更简单。用普通的CGI,你每次处理请求都得启动整个框架。
要支持WSGI,你需要安装一个WSGI模块(比如mod_wsgi),或者使用一个内置WSGI的网络服务器(比如CherryPy)。如果这两者都不行,你可以使用PEP中提供的CGI-WSGI桥接。
WSGI、CGI和框架之间是怎么联系的?
Apache是一个服务器,它在80号端口上监听请求。当它收到一个HTTP请求时,会解析这个请求,找出怎么回应。Apache有很多种回应的方式。其中一种是用CGI来运行一个脚本,另一种则是直接提供一个文件。
如果使用CGI,Apache会准备一个环境,然后通过CGI协议来调用这个脚本。这就像在Unix系统中使用Fork/Exec的情况——CGI的子进程会继承操作系统的环境,包括网络连接和标准输出。CGI子进程会写出一个回应,然后把这个回应发回给Apache;最后,Apache把回应发送给浏览器。
CGI有点原始而且麻烦,主要是因为每次请求都会创建一个新的子进程,而这个子进程必须退出或者关闭标准输出和标准错误来表示回应结束。
WSGI是一个基于CGI设计模式的接口。它不一定是CGI——它不需要为每个请求都创建一个子进程。WSGI可以是CGI,但也可以不是。
WSGI在几个重要方面改进了CGI设计模式。它会为你解析HTTP请求头,并把这些信息添加到环境中。它还会把任何POST请求的输入作为类似文件的对象提供给环境。此外,它还提供一个函数来生成回应,省去了很多格式化的细节。
如果我想在基本的CGI配置上运行一个网页框架(比如web.py或cherrypy),我需要知道/安装/做什么?
记住,创建子进程是比较耗费资源的。有两种方法可以解决这个问题。
嵌入式
mod_wsgi
或mod_python
将Python嵌入到Apache中;这样就不会创建新的进程。Apache直接运行Django应用。守护进程
mod_wsgi
或mod_fastcgi
允许Apache与一个单独的守护进程(或“长时间运行的进程”)进行交互,使用WSGI协议。你先启动一个长时间运行的Django进程,然后配置Apache的mod_fastcgi与这个进程进行通信。
注意,mod_wsgi
可以在嵌入式模式或守护进程模式下工作。
当你了解mod_fastcgi时,会发现Django使用flup来创建一个与WSGI兼容的接口,利用mod_fastcgi提供的信息。整个流程是这样的。
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