The modern Python web application stack (as I understand it)
Someone recently asked me what the modern Python equivalent of CGI was. The answer started out simple but the more I wrote the more complicated it got, until it wound up here.
At their base, modern Python web applications are written to an interface called WSGI, the 'Web Server Gateway Interface', a specification for the Python environment that web applications run in. WSGI is fairly low level (roughly on the level of CGI) and generally good, although it has a number of annoying corner cases that everyone ignores in practice. Frameworks such as Django are generally WSGI applications, although if you're using a framework you usually get to ignore the WSGI level entirely because the framework hides it (and you want this hiding).
(Mechanically, a 'WSGI application' is a callable Python object that your server will call with a WSGI environment on each request. The WSGI specification describes the environment your callable object is handed, what you can do with it, and how you return the headers and text of your reply.)
To actually deploy and run a WSGI app, you need something that provides a WSGI environment; call this a 'WSGI server'. In theory your webserver could do this, translating directly from HTTP to WSGI and back, but in practice this is relatively rare (although Apache's mod_wsgi is apparently well regarded). So you usually need a level of indirection; your webserver will go from HTTP to some protocol and speak that protocol to your WSGI server, which then maps it to WSGI and runs your application. Popular protocols for this are SCGI and FastCGI; SCGI is much simpler but also less popular.
(You are not restricted to these two choices; any way of talking to your web server will do. If you want to, you can use CGI (ie, running your WSGI server as a CGI-BIN, which means starting it up from scratch on every request). If you are sufficiently crazy you can add an extra level of indirection, having your web server run CGIs which talk SCGI to your SCGI-based WSGI server.)
Today I would expect that a common Python web application stack thus looks something like this:
- the world talks HTTP to Apache or lighttpd or nginx
- your web server (whatever it is) talks FastCGI to your WSGI server (which is running as a separate, independent process or set of processes)
- your WSGI server constructs a WSGI environment from the HTTP request and calls your framework of choice as a WSGI application
- your framework calls your code
Results trickle back in reverse.
WSGI is not a completely comprehensive standard; the most important
thing it omits (as outside of its scope) is how WSGI applications get
created and configured. The WSGI specification says that WSGI servers
are handed a Python callable and they call it with a WSGI environment
on each request, but it doesn't say how the callable object is created;
that's up to your server. Each WSGI server may have a different answer
to this, and if you're writing one from scratch (for any environment)
you can pick whichever method is most convenient for you, down to
hard-coding the creation of your application callable in your
(By now there may be a de facto Python standard on how WSGI servers are supposed to do this; I haven't been paying close attention for a while.)
The WSGI specification itself is short and includes quite readable example code for simple WSGI apps and a CGI-based WSGI server (well, most of it). WSGI is really not that complicated (although there are subtle corners).