jump to navigation

On Duck Typing August 27, 2009

Posted by PythonGuy in Uncategorized.
add a comment

Ahh, the wonders of Duck Typing!

In other languages besides Python, your code will look something like this:

def myfunc(myargs):
    if myargs are not expected:
        global_error = "myargs were not expected"
        return 0 # 0 means we have a problem.
   do something with myargs
   return a valid result

There’s a lot wrong with the above. First, it should throw exceptions, not return error codes.

def myfunc(myargs):
    if myargs are not expected:
        throw ValueError("myargs are not expected")
   do something with myargs
   return a valid result

But even then, all the code inside the do something with myargs will throw an exception if myargs are not expected. So we really don’t have to check the args. (This is Duck Typing in the extreme.)

def myfunc(myargs):
   do something with myargs
   return a valid result

Interesting. Now, our code has been boiled down to everything the code is supposed to do.

Wait—what’s this? How do we handle those exceptions?

We need to add in a new code path—that is, a branch—that is executed only in an exceptional circumstance.

def myfunc(myargs):
   try:
       do something with myargs
       return a valid result
   except Exception e:
       do something with the exception
       return a different result

That’s how all you code should look like. When you have mastered this, your code size will go down considerably.

Now, for those of you doubters out there who still wonder about types and classes and interfaces and want to put things like that in the code, let me demonstrate why that is a bad idea. The practical example is that we’re going to write a function that converts a string of digits into an integer.

def atoi(a):
    digit_value = {'0':0, '1':1, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9}
    result = 0
    while a:
        try:
            digit, a = a[:1], a[1:]
        except TypeError:
            raise ValueError("Not a string: %r" % a)
        result *= 10
        try:
            result += digit_value[digit]
        except KeyError:
            raise ValueError("Unexpected digit: %r" % digit)
    return result

Note that I do no checking at all in the above code. The code is also extremely generous. It accepts any sequence of anything string-like. It will raise exceptions when two parts of the function will throw an exception. (Really, these are the only two exceptions that can be thrown.) Both of these are converted to ValueError with a useful message.

Where do the values get checked? At two places, but it is hidden from our code. First, it is checked on the subscripting of the list-like a. If it isn’t list-like, it will throw a TypeError. Second, it is checked on the key lookup in digit_value. If the key doesn’t exist, it isn’t a digit.

You could check the string with a regular expression before any of the work is done. However, you will be doubling the amount of work that is done, both by the programmer and the program. You will also increase the complexity of the code without any benefit at all. Complex code is code that hides bugs and takes time to test and debug.

Perl Really Sucks (And They Don’t Even Realize It!) September 18, 2008

Posted by PythonGuy in Python, perl.
3 comments

Perladmin takes the bait: Why “Perl Sucks” examples are always so funny is a response to my post Python Rocks (Perl Sucks).

He pretends like I’ve never heard of splice. Of course I’ve heard of splice. I’ve heard of all the functions, because I’ve read the perl man pages and reference books multiple times. It’s my job. I know perl better than anyone I know. And I work at a pretty big company with lots of very smart perl people. (I met Larry Wall once, but I can’t say that I know him, so he doesn’t count.)

But he misses the point.

Well, he got the point that I am obviously biased, in the same way a boy falls madly in love with a girl. But it isn’t blind love. I know python and perl well, too well, and I choose python.

First, let me answer a question he had:

In the Python example the variable group is an array data type so it doesn’t need de-referencing because its not a pointer. (Ahem!) Perhaps internally it is, (Good guess) and Python only has references and all functions know how to work with them. Good news for Python if it is. (Yep! Yep! Yep!) But if you’re using arrays in your Python script, you have to make an apples-to-apples (I just did.) comparison with Perl, in which case your variable is @group, and the variable doesn’t need de-referencing, thus we also resolve this issue.

The closest thing in perl to a python variable is the scalar. In fact, it is safe to say that in Python, all variables are the same thing as refs in perl. So, $group in perl is group in Python, provided that $group is a reference. (To what? It doesn’t matter.)

Now, he took several pages to try and justify perl’s existence. I will smash him with one simple point:

HE TOOK SEVERAL PAGES TO TRY AND JUSTIFY PERL’S EXISTENCE.

And in the end, this is the code he came up with, writting in perl and then python. Note that he forgets that $group and $maxNumInSubgroup may be expressions, not actual arrays. If that were the case, then you’d have to assign the expressions into $group and $maxNumInSubgroup rather than express it naturally in context.

Oh, and the #$group crap? Yeah, that refers to the @group, not $group. Got it? Don’t worry, it’s an interview question. If you see code like this in perl, you rewrite it the way I wrote it in my article so that mere mortals can understand it.

# perl
my @group = @{$group}; # Dereference, then array copy
my @subgroup = @group[0..(#$group > $maxNumInSubgroup ? $maxNumInSubgroup : #$group)];

# Python (equivalent)
group2 = group1[:] # dereference (no can do in Python!) then array copy
subgroup = group[:len(group2) > maxNumInSubgroup ? maxNumInSubgroup : len(group2)]

# Python (natural)
subgroup = group[:maxNumInSubgroup]

And he dares say:

The above end-result for the Perl code is slightly longer, but no less readable.

I pause now to allow you to clean your keyboards, catch your breath, lower your heart rate after the good belly laugh you enjoyed. Or not. Because he’s completely serious. He actually believes what he wrote, folks.

In the end, he discovered that perl’s splice and Python’s slice are two different things. See, perl’s splice changes the array being spliced. And Python’s slice, makes a new array copied from the old one. That’s a fundamental design decision.

But he mentions speed and performance. See, when you do a copy & splice in perl, you are wasting valuable time and memory. Part of that time is spent trying to remember which arguments to splice do what, and the other part is spent remembering that splice doesn’t do slice. The rest of the wasted time is spent typing it up and trying to remember that dereference @ binds more tightly than ->, so you have to put {} around the thing.

Oh yeah, and you waste some CPU and RAM as well, but who cares about that anymore?

Question: Which use case is more common?
Answer: Perl copy & splice, which is Python slice.

Question: Does Python even have splice capability?
Answer: Of course. del a[i:j] and a[i:j] = [...].

Question: Why doesn’t perl have a slice function? I mean, it’s a pretty common use case, and HOW HARD CAN IT BE TO ADD THE THING?
Answer: Stop shouting!

Other interesting things…

In fairness I should point out that the above examples would generate warnings under strict type checking. I have no idea if Python has an equivalent. If it doesn’t I would think that it is a hinderence to Python developers.

N.B what Python does vs. perl. You actually have to run this code to see why Python doesn’t need “use strict”. If you don’t run the code, you won’t understand what it does unless you already know Python and perl.

# A: perl
use strict;
print $foo;

# A: python
print foo

# B: perl
use strict;
my $foo = "bar";
print $foo;

# B: Python
foo = "bar"
print foo

If that’s too hard for you perl-gods to comprehend, let me interpret. Python’s assign is a declare and assign. That is, the “my” is hidden somewhere, obscured, forever banished. Python scoping rules are quite different than perl’s, eliminating the dynamic scope (aka, what “local” gives you) and relying only on lexical and calling scope (aka, what “my” gives you.) So we don’t need “my”, just like we don’t need @, %, $, or &, *, or anything else like that since there is only one kind of variable.

Now, as a serious aside, let me be bold in admitting that Python isn’t perfect. But it’s a world apart from perl. Heck, even Ruby kicks perl’s butt up and down the street, and Ruby sucks pretty bad too, in very serious and bad ways. When it gets right down to it, Python has some serious issues as well, but I consider them warts and not life-threatening cancers.

Perl was great, groundbreaking, revolutionary stuff in its time. My hat’s off to Larry Wall and the perl community who took on the programming language industry and won. But the victory celebration is long over and we’ve moved on with our lives to new and better fields. So has the perl community, at least most of it.

Writing a Virtual Machine in Python April 17, 2008

Posted by PythonGuy in Advanced Python, Lisp, Python.
Tags: , ,
1 comment so far

Python is the ultimate prototyping language, right?

Yes! I am glad I know it.

In a few hours last night, I was able to write a virtual machine that could power a Scheme interpreter.

(more…)

Python MUD Reborn April 15, 2008

Posted by PythonGuy in Advanced Python, MUD, Python, Web Technologies.
Tags: , ,
5 comments

I was prodded by one Jose from Spain who wanted to learn Python to revisit SimPyMUD. Of course, that project is old and dead, but I had learned enough about how to code up servers in Python in the meantime to write a new MUD from scratch in a matter of hours.

The model I used is a threaded one. Every connection gets its own thread. It is based on the SocketServer. Here’s some code to poke at.

Let me explain a little about how it works.

First, I use a TCP threaded socket server–ThreadingTCPServer. This server will spawn a new thread which calls the request handler you set with the parameters socket, (client address, client port) and the server instance.

The request handler requires a bit of magic to read and write at the same time. That magic is provided by an asyncore dispatcher. Each thread gets its own dispatch map to manage that dispatcher.

Around the dispatcher is a session object. This manages all the state of the current session. It starts off by writing out a welcome message and prompting for the login name.

The dispatcher handles writes by accumulating them in a buffer. When the dispatcher’s handle_write method is called, that’s a sign that the socket is ready to write to. The dispatcher writes as much data as it can, pulling it off of the buffer.

When an incoming bit of text arrives, the handle_read() method of the dispatcher is called. This will read as many bytes as it can, storing them in the incoming buffer. Then the buffer is split by lines and passed off to handle_read_line method. This is conveniently overridden with an attribute assignment to the dispatcher instance. Depending on the state of the session, that input will be rerouted to one of different places.

(An alternate implementation could keep track of the state and then have methods for all of the states. I would rather take advantage of Python’s dynamic environment than keep the rules of C.)

In the login state, input is read and when it is non-blank, it is stored as the login name. Then the state moves to the password input state. There, input is read that represents the password. The corresponding player is looked up in the database (really, a dict) and if one matches with the login and password, then the state moves to the playing state with the player assigned accordingly. Otherwise, an error message is shown and the state transfers back to the login mode.

In the play mode, commands are parsed. The commands dispatch to one of the command methods, which are supposed to do further parsing of the input. Based on the command, objects in the universe are modified, messages are sent out to different connections, and basically, stuff happens.

Thus, you have a MUD.

Now, in building a MUD, there are two bits you have to work on: (1) The functionality, (2) the world. The functionality, for the most part, is going to be implemented in python. New commands are new methods in the play state. Objects also have some methods that are invoked by the commands. If you want a new feature, you’ll have to change existing commands or add new ones.

The world, however, is represented with data. These are the object instances that have been created and linked to each other.

Python doesn’t do a tremendous job of allowing functionality to be represented with data. Ideally, I can imagine a mud universe where everything is code or everything is data because data and code are the same thing. (I guess I have been reading too many Lisp books.) You could log into this world and, as an administrator, change the very rules of nature. But with Python, I don’t quite see a way to do that without either implementing a new language inside of Python, or finding some way to record the Python program state. When I figure it out, I am sure there is some Python award or something.

An alternative method of implementing a MUD, one that I would like to explore, involves using greenlets to simulate threads while truly doing asynchronous socket programming. (the eventlet module is very interesting.) This is an interesting idea because the functionality doesn’t have to be implemented with states. It can be implemented with pure functions that are interrupted and resumed appropriately. It is kind of like the anti-Twisted environment.

Python Typing: Just the Right Amount March 22, 2008

Posted by PythonGuy in Java, Lisp, Python, perl.
add a comment

So, I’m reading some blog posts from who-knows-when. I closed the pages and it is lost to my memory, so sorry I can’t uncover it.

A few points seemed to bleed through, though:

1. Dynamic typing (that is, not specifying the type of the objects at the time of coding) is a good thing, since getting static typing (the opposite) correct is very hard. In fact, Haskell and other languages make a really, really good effort at it, almost get it right, but still don’t solve the problem of making the code easier to read, write, and maintain than dynamically typed languages. So, in the boxing match of static typing vs. dynamic typing, dynamic typing wins by forfeit.

2. Strict typing (that is, specifying the type of the object upon inspection) is a good thing, since loose typing (not knowing what type a thing is, even after looking at it very hard) is terrible. In this boxing match, the opponent is so ugly and so hard to deal with, that the audience boos him out of the ring before the match can start. Strict typing wins.

So, the ideal language will be dynamic and strict (python, lisp), not static or loose. (Although, if someone figures out the static typing thing without making life harder, there could be an upset. This is unlikely, since writing strict typing code that works is as hard as writing code.)

Some people nowadays are trying to bring in some form of static typing to python. Python 3k will have it, to some degree. However, it is not really going to be implemented at compile time. it will be an additional parameter check at runtime that will throw an exception should the static type check fail.

I have a bold prediction: In the end, no one is going to use the static typing features of Python. How do I know this? Because perl tried something similar, and it fell by the wayside, hard.

Granted, perl’s typing system was extremely naive and difficult to use. But it is a testament to me that I don’t see any new code with it being used. In fact, I bet you could just ignore the whole thing—just pass those constructs up and not even recognize them—and the old code that uses them won’t even notice. This is partly because the code that is calling the statically typed subroutines are already debugged, but also because if there is an issue, it will come up. If there isn’t, it won’t.

Duck typing these days is taking a lot of hits. That’s unfortunate, because duck typing is the exact amount of typing we need. Duck typing, in the end, says, “Who cares what type it is? I’m just going to use it and if it wasn’t duck enough, we’ll be eating patte of whatever you passed me.”

See, sometimes I do know better than the person who implemented the function what should be passed in. Sometimes I want to sneak something in that is not expected. Here’s an example: The sys.ps1 global variable in the sys module. At first glance, 99% of the programs would say, “That should always, 100% of the time be a string.” But then that 1% who actually seriously use BASH everyday and know that $PS1 is most definitely not a string but actually a piece of code written in a special language will pipe up and say, “That is most definitely *not* a string. It is something that could be turned into a string, but that’s all it is.”

Sometimes, the people who put the guts inside of the black box are too strict. Sometimes they overestimate what the requirements for input are. And sometimes people who use those black boxes know better.

So let’s leave our contracts where they belong—in the documentation. Let’s allow coders to put together their systems and see if they work, to learn how the black boxes work better than the people who made the black boxes. In other words, let’s keep our noses out of each other’s business.

Teaching my Son Python March 18, 2008

Posted by PythonGuy in Beginning Programming, Education, Python.
add a comment

I home school my son. Why? Well, that’s a whole other ball of wax.

One of the opportunities that home schooling affords is I get to choose the curriculum. Part of that curriculum includes learning to program. Whether my son decides to be a lawyer, a plumber, or a high-energy particle physicist, I expect that at least the understanding of how to program will come in handy.

I started to learn to program when I was just a bit older than him on an old Commodore 64 with BASIC. He just turned 7. I had tried some experiments earlier to see if he could “get” programming, at least the most fundamental concepts last year, and I had prodded lightly over the year. But this time, he seems to start to “get” it.

At first, he used it like a calculator. You type in the numbers to the Idle prompt, and out comes the same number. You put in a +, -, *, or / and it does all the hard work for you. (He doesn’t know about decimals yet—although he knows how to add and subtract money including cents.)

What really fascinated him was this short program, written in Python 3.0:

import random

def guess_my_number():
  number = random.randint(1,1000)
  while True:
    guess = int(input("Guess my number: "))
    if guess > number:
      print("You're too high!")
    elif guess < number:
      print("You're too low!")
    else:
      print("You got it! You must be very smart.")
      break

This is a very simple program, but it plays a game with my son that requires him to think logically and almost run a similar program, almost as easy to write:

import random

def let_me_guess():
  high = 1000
  low = 1
  while True:
    guess = random.randint(low, high)
    answer = input("Is it %d? (yes/low/high) " % guess)
    if answer == 'yes':
       print("That was fun!")
       break
    elif answer == 'low':
       low = guess + 1
    elif answer == 'high':
      high = guess - 1
    else:
      print("I didn't understand you.")

Now, I didn’t write the programs perfectly the first time, but thanks to Idle it was a trivial matter to find and fix bugs. I am not entirely certain that the above two programs work—I typed them from memory. But if they don’t, it would be a good learning experience to make them work. So he got to see part of the development process—write, rum debug, repeat.

Having the computer be just as smart as dad at guessing a number was an interesting revelation to my son. I guess something clicked in his head that there was something magical happening inside that strange metal box, something that wasn’t completely beyond explanation and something he could harness. After seeing the computer guess his number, he began playing guess_my_number() again and again. In that process, he discovered a bug. If you type in a very large number, then the whole thing throws a ValueError. He actually made it a game of seeing what input caused the error and what didn’t.

I tried to play with the debugger, but I hardly ever use it and it didn’t seem to do what I wanted anyway. It would’ve been neat to show my son how the program actually ran, but truthfully, if you don’t understand the concepts, it will still be mysterious.

It also reminded me about how much “art” (art as in technical experience, know-how) goes into programming. You have to know how to use the keyboard, run programs, debug programs, use a text editor, and a whole number of things. If all of these pieces don’t come together, if you’re deficient in one area, you can’t program. It would be nice if we could make the programming task even simpler by removing some of these dependencies—dependencies with really didn’t exist in the C64 era—but alas, I don’t see a way to do it and still write “real” programs.

Line-at-a-Time Interactive Input March 12, 2008

Posted by PythonGuy in Advanced Python, Python, Text Handling.
add a comment

Let’s write a line-at-a-time interactive console.

Here’s how I would write it without knowing much about Python:

#!/usr/bin/env python

import sys

for line in sys.stdin:
  print "You wrote:", line
print "Goodbye!"

Except that doesn’t work. See, the input on stdin is buffered. That means, until a certain amount of input is reached, no lines are generated. Looking around, there is no way I can see to turn off buffering. Ugh.

Now, don’t get me wrong. The above method is by far the best way to process line-at-a-time files, just not interactive input. I would use it for cases when you are piping in the output of another process into this Python process, of for cases where you are loading a file.

But for reading a terminal (or for that matter, reading sockets) it’s not the best way to go, thanks to buffering.

Well, how does one do this the Python way? I saw some notes on raw_input(), but I didn’t want to go there. (I end up there anyway. You’ll see.)

What about Logix? Logix is a language written in Python, and they have an interactive console just like Python’s. How did they do it?

Looking in their code, they simply subclassed code.InteractiveConsole, and overrode some features. In particular, they messed with sys.ps1 and sys.ps2 (being careful to remember what they were and restoring them when they were finished.) But as far as the InteractiveConsole is concerned, they pretty much overrode the runsource method with their own.

So, the line-at-a-time input program, at a minimum, would look like this:

#!/usr/bin/env python

import code

class InteractiveConsole(code.InteractiveConsole):
  def runsource(self, source, filename='', symbol='single'):
    print "You wrote:", source
    return False # return True if you want more

InteractiveConsole().interact('')
print "Goodbye!"

This is much better. If you are writing a language interpreter for a new language you are writing in Python, then this is a great place to start. It really is a natural fit.

But, what if you want something simpler? Well, raw_input() is really the way to go.

#!/usr/bin/env python

while True:
  try:
    line = raw_input()
  except EOFError:
    break
  print "You wrote:", line
print "Goodbye!"

This is about the most basic form you can have.

I experimented with converting the above to a generator so you can write for line in input():, but I realized that it’s not really practical. Sometimes you may want to change the prompt, or do something else. So that’s not the best form for line-at-a-time interactive work.

One more note: If you want the full, interactive console with history, you’ll have to import readline. This is for both the raw_input method and the code.InteractiveConsole method. Note that if you are already in the interactive console for Python, readline may already be imported.

Python Rocks (Perl Sucks) March 4, 2008

Posted by PythonGuy in Python, perl.
9 comments

Arg! Reading this in perl will make you scream, even if you know and love perl:

my @subgroup = (scalar(@{$group}) > $maxNumInSubgroup) ?
    @{$group}[0..($maxNumInSubgroup-1)] :
    @{$group};

First, I hate the way perl doesn’t treat every variable as equals. Why can’t everything just be a ref like in Python? Because of this, you have to worry about dereferencing, which makes nobody’s code beautiful. Even when you try to be consistent (as the author above is, thankfully), you still have to know about the other five or six methods of dereferencing.

Aside from that, Python’s indexing is one of its biggest strengths because it is consistent and beautiful. The above translated into Python:

subgroup = group[:maxNumInSubgroup]

Note that the resulting subgroup will not exceed the size of group, even if group has less items than maxNumInSubgroup.

Note that you have no “-1″’s to get the array the right size.

Note also the absence of casts. Perl’s scalar cast on a list is one of the most wrong-headed decisions of all time. If I wanted to know the length of an array, I would ask for it explicitly. Of course, I hardly ever care what the length of an array is.

One more benefit… count the number of times you had to write “group” and “maxNumInSubgroup” in the perl and Python examples. Since you only had to write it once in Python, you can substitute the variable name for the expression that gave you the value in the first place. For example, compare the following two code samples:

Perl:

my $maxNumInSubgroup = pageSize/3 + 5;
my $group = getGroup(param1, param2);
my @subgroup = (scalar(@{$group}) > $maxNumInSubgroup) ?
    @{$group}[0..($maxNumInSubgroup-1)] :
    @{$group};

Python:

subgroup = getGroup(param1, param2)[:pageSize/3+5]

Not having to be repetitive means you don’t have to come up with new temporary variable names when they aren’t really necessary. It also reduces the complexity and length of your code.

Python wins. Perl loses.

Calculating the Number of Pages March 4, 2008

Posted by PythonGuy in Uncategorized.
add a comment

This is a minor thing, but something I feel like every young programmer should know.

How many pages of n items per page are needed to show t items?

If we are showing, for instance, 3 items per page, and we have 6 items, we only need 2 pages. But if we have 7 items, we need 3 pages. One page will only have one item.

How can we translate this into an algorithm?

This is the most disgusting example I have seen so far. Yes, it’s easy to understand, but no, it isn’t simple.

# This is how many will be on the last page, if we need it.
remain = t % n

# This is how many full pages we will have
pages = (t - remain) // n

# We need one additional page for the remaining items.
if remain:
    pages += 1

This is terrible. I don’t like it because it is wordy, and confusing to boot.

Here is a much better method.

pages = 1 + ((n-1) // t)

What is happening here? Well, if you are curious, you can plug in a few numbers.

If you put t = 3, n = 0, then you will get pages = 1 + (-1 // 3) => 1 + -1 => 0

If you try t = 3, n = 5, then you get: pages = 1 + (4 // 3) => 1 + 1 => 2

Try t = 3 and n = 6, then you get: pages = 1 + (5 // 3) => 1 + 1 => 2

Python Guy Gets WSGI February 25, 2008

Posted by PythonGuy in Advanced Python, Python, WSGI, Web Technologies.
add a comment

Thanks to patient explanation by an article written by James Gardner, this old web programmer gets the point of WSGI.

Let me say, WSGI rocks my world. It’s one of those things that says, “There’s a whole fresh new world of opportunity out there, and you’re invited.”

Before WSGI, the web world was strange and convoluted. You had to either edit a slew of Apache config files (which, while better than the predecessor, was still a major pain). Or you had to build your own web server (which, while better than before, was still painful.)

Apache was nice because you could use something like mod_perl or mod_python and actually get in there and change the way the request was handled. It was bad because the request stack was extremely complicated, and the config files didn’t make any sense to the new Apache hacker.

Hand-coded web servers were not nice because each one was different, and most were not that flexible. In the end, you had a new hand-coded web server that was incompatible with the last one. Hence, we have seen Zope and Django succeed.

Ruby-on-rails merely opened the world’s eyes to what a good set of options can give you in the world of hand-coded web servers. It is, in a way, the apex of that kind of technology.

However, WSGI is a whole new experience. It is a combination of the best parts of hand-coded web servers, with the best parts of the Apache request stack. Now, before you start pulling your hair out because it sounds so complicated (you mean I have to wrestle with config files and hack on web servers?), realize that WSGI is the simplest solution one could ever possible come up with.

It has, in its interface, three parts.

First, WSGI handlers are functions. (That’s not rocket science. Apache request handlers were functions. RoR controllers are, ultimately, functions.)

Second, the function takes exactly two parameters. The parameters are “environ” and “start_response”. “environ” is a dictionary, a map. It can list whatever you want. Some things are expected, but they don’t have to be. In different parts of the stack, people will expect different things. “environ” is by far the most complicated part of WSGI, and it is only complicated because different people will need and provide different keys. “start_response”, on the other hand, is a function. It takes a response code (“200 OK”) and a list of HTTP headers.

Third, the WSGI handler must return something iterable. This is going to be the body of the HTTP response.

Pretty simple, huh?

Now, let’s consider what you can do with this.

Obviously, you can create your hand-coded web application. It will simply be a WSGI handler. It will call “start_response” with the appropriate parameters, and then send back the body of the response. Plug this in to any default web server that supports WSGI, and viola! You have a working web application where you can replace the underlying technology. One solution fits all.

Or, you can create a WSGI server. This would take incoming HTTP requests and translate them into WSGI requests. It would take the response and send it out as an HTTP response. Pretty simple, huh? Well, the possibilities are endless. In fact, there are already WSGI handlers for pretty much anything you can imagine, as well as CGI-WSGI translators if you just want to work from the CGI environment. Your options are endless—and they are all interchangeable. One solution fits all.

Or, you can write WSGI middleware. What is middleware? It is what you can put between the web server (which handles the HTTP request and sends an HTTP response) and the web application (which does something interesting with the request.) For instance, if you wanted to do HTTP AUTH, you could write a WSGI middleware app that takes the incoming WSGI request, checks to see if it has been authenticated, and returns an auth request if not. Otherwise, it just passes it along, adding who was authenticated to the environ. You could write an error handler. It would catch exceptions and show a very neatly formatted web page, one that could even allow people to play with the program state. The possibilities are endless. And best of all, middleware is universally useful. One solution fits all.

In short, thanks to WSGI, the world of web application development just got a lot easier, and your options just got a lot bigger. You can literally remove one component of the request stack and replace it with another. And the interface is quite simple.

Now, once you understand this, and once you actually get around to building a web application with six or seven different pieces, you are going to find that the hardest part is configuration. Getting all the pieces configured to behave just the way you want is going to be a bear, because each one is configured in its own way. Never fear, that’s what Python Paste is for. Python Paste takes a config file (in .ini format) and configures each component on the stack. You just have to write the code that puts it together, informing each part that there is a configuration for it from the paste infrastructure.

Python Paste also handles some fairly common tasks, tasks that many different components will want to do. For instance, given a WSGI request, try to build the URL that generated that request. These util functions are actually quite simple. Take a look at them if you get a chance. But they are useful for anyone who is doing any work anywhere on the WSGI stack.

So Python Paste makes it really easy to put together your WSGI app and configure it.

With Python Paste and WSGI, your possibilities have grown significantly, and the overhead has dropped just as much. Now, more than ever, it is going to be possible to build web apps in an afternoon.