Toolserver:Python WSGI


This page was moved from the Toolserver wiki.
Toolserver has been replaced by Toolforge. As such, the instructions here may no longer work, but may still be of historical interest.
Please help by updating examples, links, template links, etc. If a page is still relevant, move it to a normal title and leave a redirect.

The Python Web Server Gateway Interface is a standard interface between web servers and Python web applications or frameworks, to promote web application portability across a variety of web servers. It is fully defined in PEP 333

It uses methods similar to CGI, so that Python programs are easily ported to WSGI.

Converting CGI to WSGI[edit]

WSGI consists of an application and a gateway. The gateway translates the CGI/FCGI/SCGI/AJP request to WSGI. The stable server has Flup installed as WSGI gateway.

The application must first register itself with the WSGI gateway by providing a callable object to the gateway (a function or an object that implements __call__). When a request comes in the gateway will call the application via this callable, passing on a function start_response and an environ dictionary.

This callable should return an iterable object, such as a list or a string. This data will be passed to the client. Note that by using generators it is possible to send data while the function is still being executed. However, only yield values after start_response has been called.

Files should have the .fcgi extension.


The environ dict provides CGI variables in a similar fashion as CGI. The stdin used in CGI to read postdata is replaced by environ['wsgi.input'], which is a file like object. For more information see the specification.

def application(start_response, environ):
  # Simple WSGI example
  query_string = environ['QUERY_STRING']
  postdata = environ['wsgi.input'].read(int(environ['CONTENT_LENGTH']))


The start_response function is a function that indicates that sending data may start. It accepts the parameters status and headers, which indicate the HTTP status code and HTTP headers to return.

  # Continuation of the previous example
  start_response('200 OK', [('Content-Type', 'text/html; charset=utf-8')])
  return ['Your query string is:\n<pre>', repr(query_string), '</pre>\n']


The web server has flup installed, which acts as a gateway for WSGI. Flup supports CGI, FastCGI, SimpleCGI and Apache JServ Protocol, making it useable on both the regular toolserver as the stable server.

# Other available modules in flup.server are 
# ajp, ajp_fork, fcgi, fcgi_fork, scgi, scgi_fork
# The *_fork version are prefork version of the WSGIServer,
# the others are multithreaded. If you don't know the
# difference between them, always choose the prefork.
from flup.server.cgi import WSGIServer
wsgi = WSGIServer(application)

Hello world[edit]

#!/usr/bin/env python
def myapp(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])
    return ['Hello World!\n']
if __name__ == "__main__":
    from flup.server.fcgi import WSGIServer


  1. WSGI programs should have the .fcgi extension, and be located outside ./cgi-bin. Standard CGI programs should have the .cgi extension, and be located inside ./cgi-bin. See Web hosting for more info.
  2. The number of concurrent WSGI instances can be more then available database connections

See also[edit]

External links[edit]