如何将 CGI 转换为 WSGI?

Swe*_*man 0 python apache cgi mod-wsgi wsgi

我继承了一个使用 CGI 脚本的代码库。据我所知,它们效率很低,因为每次收到请求时它们都会分叉一个新进程。我目前正在尝试将它们转换为 WSGI,但我对以下内容感到困惑:

  1. WSGI 和 CGI​​ 在代码方面有何不同?我知道该应用程序必须是可调用的,但除此之外,我不确定还需要做什么来更改它。

  2. 我如何衡量我所看到的效率提升随着变化而明显的变化?

其他可能有用的信息是我将使用 Apache 和 mod_wsgi。

如果我可以提供任何其他信息,请告诉我。

Sin*_*ion 5

在某些方面,wsgi 将 cgi 所做的一些事情抽象为纯 python 函数调用,没有副作用。

CGI 程序的“输入”是进程环境,在os.environ和中sys.stdin。此类程序的输出是sys.stdout,错误从 到达服务器日志sys.stderr

wsgi 应用程序是一个带有两个参数的 python 函数,通常称为environ(这将是一个dict) 和start_response(这将是另一个函数)。

第一个参数是 a dict,包含 cgi 程序将获取的所有内容os.environ,但它还包含几个额外的键。值得注意的是,它包含"wsgi.input"一个类似文件的对象,它取代了sys.stdin请求正文。

CGI 程序sys.stdout同时使用 HTTP 响应行、响应标头和响应正文。在 wsgi 程序中,前两个作为参数传递给start_response参数。wsgi 响应正文不会**写入文件;相反,它是从应用程序函数返回的。

典型的 CGI 程序可能如下所示:

import os, sys
request_size = int(os.environ.get("HTTP_CONTENT_LENGTH", "0"))
person = sys.stdin.read(request_size)

response = "Hello %s!\n" % person
print "Status: 200 OK"
print "Content-Type: text/plain"
print "Content-Length: %d" % len(response)
print
print response
Run Code Online (Sandbox Code Playgroud)

等效的 wsgi 程序如下所示:

def myApp(environ, start_response):
    request_size = int(environ.get("HTTP_CONTENT_LENGTH", "0"))
    wsgi_input = environ.get("wsgi.input")
    person = wsgi_input.read(request_size) if request_size and wsgi_input else ""
    response = "Hello %s!\n" % person

    start_response("200 OK",
        [("Content-Type", "text/plain"),
         ("Content-Length", str(len(response)))]

    return [response]
Run Code Online (Sandbox Code Playgroud)

* 出于技术原因,有一个可选的第三个参数,主要用于“中间件”
** 为了与旧的 Web 框架兼容,start_response() 返回一个可以写入的类似文件的对象,但不建议这样做。在您的情况下,它可能会简化转换,但由于无论如何都需要侵入性更改,请看看是否可以避免它。