如何将CGI转换为WSGI?

时间:2014-06-10 20:14:36

标签: python apache cgi mod-wsgi wsgi

我继承了使用CGI脚本的代码库。从我读到的内容来看,它们效率低下,因为每次请求进入时都会分叉一个新进程。我现在正试图将它们转换为WSGI,但我对以下内容感到困惑:

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

  2. 如何根据变化对我所读效率的提升进行基准测试?

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

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

1 个答案:

答案 0 :(得分:4)

在某些方面,wsgi将cgi中的一些东西抽象为纯python函数调用,没有副作用。

"输入"在os.environsys.stdin中,过程环境是一个cgi程序。此类程序的输出为sys.stdout,错误从sys.stderr到达服务器日志。

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

第一个参数是dict,包含cgi程序在os.environ中获得的所有内容,但它还包含一些额外的键。值得注意的是,它包含"wsgi.input",这是一个类似文件的对象,它代替请求体的sys.stdin

cgi程序对HTTP响应行,响应头和响应正文使用sys.stdout。在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

等效的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]

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