简体   繁体   中英

How do I Convert CGI to WSGI?

I inherited a code base that uses CGI scripts. From what I read they're inefficient because they fork a new process every time a request comes in. I'm currently attempting to convert them to WSGI but I'm confused on the following:

  1. How are WSGI and CGI different code-wise? I know that the application must be callable but other than that, I'm not sure on what else I will have to do to change it.

  2. How do I benchmark the increase in efficiency that I read should be obvious with the change?

Other info that might be useful would be that I'm going to be using Apache and mod_wsgi.

Let me know if there's any other info I can provide.

In some ways wsgi abstracts out some of the stuff cgi does into a pure python function call, with no side effects.

The "inputs" to a cgi program are the process environment, in os.environ and sys.stdin . The output to such a program is sys.stdout , with errors reaching the server log from sys.stderr .

A wsgi application is a python function taking two* arguments, usually called environ (which will be a dict ) and start_response (which will be another function).

The first argument is a dict , containing all of the things a cgi program would get in os.environ , but it also contains a couple of extra keys. Notably, it contains "wsgi.input" , a file-like object which takes the place of sys.stdin for the purposes of request body.

A cgi program uses sys.stdout for both the HTTP response line, response headers, and response body. In a wsgi program, the first two are passed as arguments to the start_response argument. A wsgi response body is not** written to a file; instead, it's returned from the app function.

A typical CGI program might look like this:

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

The equivalent wsgi program would look like:

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]

* for technical reasons, there's an optional, third argument, mostly for "middleware"
** for compatability with old web frameworks, start_response() returns a file-like object that can be written to, but this is not recommended. In your case it might simplify the conversion, but since an invasive change is needed anyway, see if you can avoid it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM