我继承了使用CGI脚本的代码库。从我读到的内容来看,它们效率低下,因为每次请求进入时都会分叉一个新进程。我现在正试图将它们转换为WSGI,但我对以下内容感到困惑:
WSGI和CGI在代码方面有何不同?我知道应用程序必须是可调用的,但除此之外,我不确定我还需要做些什么来改变它。
如何根据变化对我所读效率的提升进行基准测试?
其他可能有用的信息是我将使用Apache和mod_wsgi。
如果我能提供任何其他信息,请告诉我。
答案 0 :(得分:4)
在某些方面,wsgi将cgi中的一些东西抽象为纯python函数调用,没有副作用。
"输入"在os.environ
和sys.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()返回一个可以写入的类文件对象,但不建议这样做。在您的情况下,可能简化转换,但由于无论如何都需要进行侵入式更改,请查看是否可以避免它。