WSGI demystified

One of the most exciting things to come out of PyCon 2005 was the WSGI spec. WSGI is a standard that specifies a common interface for Python Web frameworks.

For a full understanding of the interface there’s no substitute for reading the spec. But in my experience, many people are too busy to read specs. So here’s an executive summary of how WSGI works.

WSGI actually specifies two interfaces, one for the server to talk to the application, and one for the application to talk to the server. For the server to talk to the application, it calls a function (which the application supplies) which should accept two arguments, environ and start_response. The environ argument will be a dictionary containing the HTTP environment (including variables like REQUEST_METHOD and PATH_INFO), and the start_response argument will be a function.

For the application to talk to the server, it should first prepare any headers it wants to send, then call the start_response function that it was handed, with a status code and a set of headers. Then it should prepare the body of the response as a list of strings. (An iterator can be used instead of a list). To pass the response body back to the server, it should simply return it.

Once the server receives the list (or iterator) from the application, it simply sends those strings, one at a time, to the client (i.e., the user’s Web browser).

Got that? Here’s what it looks like in Python code:

def simple_app(environ, start_response):
    status = '200 OK'
    response_headers = [('Content-type','text/plain')]
    start_response(status, response_headers)
    return ['Hello world!n']

There you have it — the WSGI interface in a nutshell. The server invokes the application by calling a function, then sends the function’s return value(s), one at a time, back to the client. Pretty simple, eh?

There are a lot of subtleties that I haven’t covered, of course, such as the contents of the environ dictionary, or the fact that the application doesn’t have to be a function, but can be any callable object (such as a class). To grasp those, you’ll have to read the spec. But just understanding the concepts presented here is a good jumping-off point to make the spec a lot less mysterious.

Update, 2005-08-15: There’s a simpler way to write my simple_app example: as a generator. In fact, that’s probably a simpler way to write any WSGI app. Instead of building a list of strings and returning the list, simply use yield statements, thus:

def simple_app(environ, start_response):
    status = '200 OK'
    response_headers = [('Content-type','text/plain')]
    start_response(status, response_headers)
    yield 'Hello world!n'
    yield 'Second line goes heren'

Simple, eh?

Long filenames in Windows

Long file names in Windows are a hacked-in kludge, and sometimes it shows. Here’s an example of how, if you’re not careful, you can lose data:

C:TEMP>mkdir robintemp

C:TEMP>cd robintemp

C:TEMProbintemp>dir
 Volume in drive C has no label.
 Volume Serial Number is C899-6ADC

 Directory of C:TEMProbintemp

01/28/2004  02:26p      <DIR>          .
01/28/2004  02:26p      <DIR>          ..
               0 File(s)              0 bytes
               2 Dir(s)  34,996,314,112 bytes free

C:TEMProbintemp>echo Hi > longfi~1

C:TEMProbintemp>dir
 Volume in drive C has no label.
 Volume Serial Number is C899-6ADC

 Directory of C:TEMProbintemp

01/28/2004  02:26p      <DIR>          .
01/28/2004  02:26p      <DIR>          ..
01/28/2004  02:26p                   5 longfi~1
               1 File(s)              5 bytes
               2 Dir(s)  34,996,314,112 bytes free

C:TEMProbintemp>dir /x
 Volume in drive C has no label.
 Volume Serial Number is C899-6ADC

 Directory of C:TEMProbintemp

01/28/2004  02:26p      <DIR>                          .
01/28/2004  02:26p      <DIR>                          ..
01/28/2004  02:26p                   5                 longfi~1
               1 File(s)              5 bytes
               2 Dir(s)  34,996,314,112 bytes free

C:TEMProbintemp>echo Hi > longfilename01

C:TEMProbintemp>dir /x
 Volume in drive C has no label.
 Volume Serial Number is C899-6ADC

 Directory of C:TEMProbintemp

01/28/2004  02:27p      <DIR>                          .
01/28/2004  02:27p      <DIR>                          ..
01/28/2004  02:27p                   5 LONGFI~2        longfilename01
01/28/2004  02:26p                   5                 longfi~1
               2 File(s)             10 bytes
               2 Dir(s)  34,996,314,112 bytes free

C:TEMProbintemp>mkdir ..foo

C:TEMProbintemp>copy *.* ..foo
longfilename01
longfi~1
Overwrite ..foolongfi~1? (Yes/No/All): n
        1 file(s) copied.

C:TEMProbintemp>

See what happened? The file longfilename01 was copied first, thus creating the short filename longfi~1 according to Microsoft’s filename-creation rules. But the next step was to copy the file longfi~1 from the source directory, and oops! It already exists in the destination!

What should have happened here is that the file longfilename01 should have kept its short file name longfi~2 when it got copied; then there wouldn’t have been a filename collision.

And lest you think this is a contrived example: I ran into exactly this problem about a year and a half ago when trying to do some backups. The solution I came up with was to hack together a quick script that would first copy all the 8.3 filenames, and second copy all the long file names. Then I could be sure that the shortnames chosen by Windows wouldn’t accidentally conflict with a file that was going to get copied over later.

I hope this spares someone some pain someday.

SQLite embedded in Tiger

In the middle of Apple’s Web site, in a discussion of their new Core Data framework, comes the following quote:

SQLite is an open source embedded database that is included in Tiger [...]

This makes me happy. SQLite is one of the most useful embedded-database solutions I’ve come across. It’s open-source, has Python bindings, and works with the very cool SQLObject module.

Vim Outliner

I’ve just discovered a very useful outliner for Vim. I’d never really been happy with the todo list management programs I’d tried before — well, now I can use my favorite text editor to track to-do lists and other miscellaneous items for Getting Things Done. I may have to write a longer post about it once I’ve used it for a little while.

Pardon my dust…

My new blog is up, and will be getting some content soon. I’m still getting the look worked out, so you might see some changes as I re-arrange categories, tweak the look of the title, etc. No worries!

« Previous Page