WSGI on the Rocks

Especially as a Python web developer, you should have heard of it: WSGI, the Web Server Gateway Interface, sometimes pronounced as "whiskey" and defined in PEP 333 (Python Enhancement Proposal) by Phillip J. Eby (who is also known for making life easier with setuptools). As the name suggests, it describes an interface for interaction between web servers and web applications. Although the idea and specification have been around for some years now and I did read about it here and there, I didn't manage to get deeper into the subject for quite a long time.

Until a few weeks ago. As a start, I began porting a very basic site of mine to WSGI. It only reads data from flatfiles and wraps it into a nice presentation; no user interaction, no fiddling with HTTP headers and the like. It worked out pretty well, and shortly, after being enlighted by temporarily making use of Luke Arno's yaro, I had made the site a WSGI application, running both as CGI behind Apache using wsgiref.handlers.CGIHandler from the wsgiref package (already comes with Python 2.5) as well as a stand-alone application using wsgiref.simple_server, complemented by static (also by Luke Arno) for local delivery of static content (while Apache is directly used for that online). With that experience, I upgraded another, though somewhat more complex site to WSGI with ease, too.

homework prod., this very site, was the next on the list, and I planned to do a stepwise conversion due to its slightly advanced capabilities like file pass-through, file download, feed generation and (mostly administrative) user input processing, which might raise problems. Which is what they did.

Having used some of Luke Arno's WSGI projects so far, I finally "got" what Ian Bicking's Paste package is about and integrated some of its modules into my code. Together with lots of looks into the source code of the Pylons project, itself extensively built on top of Paste, I was able to complete the transition of my site to WSGI. Next steps will be refining some code and probably sourcing out some components as WSGI middleware, e.g. the authentication layer (and maybe AuthKit triggers some good inspirations). Also, I want to get into Paste Deploy and Paste Script to push my development efficiency even more.

Now make it faster

Not only have I learned lots of interesting and indeed very cool things about how to build clean web applications (at least with Python, for now), I also used the gained flexibility to make the outstanding step up the deployment ladder and switched from plain old CGI to FastCGI (therefore replacing wsgiref.CGIHandler with flup.server.fcgi.WSGIServer from Allan Saddi's flup package). According to the ApacheBench utility, performance increased by a factor of eight. Nice. On the other hand, the results show that if this site would be slashdotted, it is still screwed big time.

Since the (Fast)CGI WSGI handlers, or at least those I use, do not set the PATH_INFO environment variable (which might be the correct behavior in these cases), I wrote a small middleware class to fill it from the REQUEST_URI:

class FixingMiddleware(object):

    def __init__(self, app): = app

    def __call__(self, environ, start_response):
        environ['PATH_INFO'] \
            = environ.get('REQUEST_URI', '').split('?', 1)[0]
        return, start_response)

To put it into the WSGI stack:

# where ``app`` is your application
app = FixingMiddleware(app)

There is a drawback, but that might apply for every non-CGI application: If the application's files are upgraded, it has to be restarted (meaning an Apache reload, as far as I can tell). That reminds me of not to develop online ;).


Altogether, I heavily recommend to learn and use WSGI. Some good articles appeared lately, I suggest Introducing WSGI: Python's Secret Web Weapon, Part One and Part Two by James Gardner as well as Google TechTalk on WSGI, Middleware, Paste, and Pylons by Ben Bangert to get the idea of WSGI and how to use it (and yes, those two are the main developers behind Pylons). Continuative links are available at