Archive for the ‘web’ Category

Google AppEngine: YAPWF (Yet Another Python Web Framework)

I’ve been playing around with Google’s new hosted Python framework. I created a very basic wiki called WikiWikiWoo! just to get a feel of the system.

It’s based on Django and Paste and seems to be inspired by bits of web.py and maybe bits of Werkzeug.

The templating is directly Django’s, which I think is a shame as Jinja is very similar but better (vaguely useful error messages for a start).

The model is inspired by Django, but using Google’s Datastore (not an rdb), using GQL, their modified version of SQL. It wasn’t easy to get going with, which is partly the fault of the documentation (it took me ages how to work out how to do their version of a primary key).

Once you get the hang, it’s pretty simple for quick simple data. It would be tough going to work out how to do complex relationships with it, particularly for anyone from a traditional rdb background (like me). There’s no section where they explain how their datastore works and the concepts behind it. I’ve been playing with Couchdb recently and they did a wonderful job of explaining the overall concept before going into how to use it. That kind of conceptual overview for Datastore would probably make a world of difference.

The controllers seem to be inspired by Web.py. They are classes with methods for POST, GET, etc. I like that system from playing around with Web.py. It allows you to very easily use the same URL for displaying an edit form and saving an item. It keeps your code nicely grouped, but I think it would make it a little more difficult to create generic CRUD controllers (maybe having to use meta-class magic).

The routing seems based on a corrected version of Web.py’s. It fixes the annoying list of tuples into a proper list of lists of tuples. It uses basic regexs for routing (first one that matches wins), and a direct reference to a class. This means the routing has to go at the end of the module (which is different to most other frameworks). I like it and it’s exactly how I set up the routing when I was messing around with WSGI.

Sessions and deployment are the killer features. Deployment is just a single command that uploads all your files, and restarts your app. Session handling uses the Google login system, so sessions are completely abstracted away. These are often the hardest bits to get right when using a new framework, so they’ve done impressively well to make them so simple.

Overall, I’d say it could be outstanding for quickly knocking out an app you’ve just thought of. A simple app will scale beautifully if it suddenly becomes popular (no more slashdotting) and they’ve solved the more annoying problems for webapps. I would have some concerns about trying to create a huge complex app using it, but we’ll see. Certainly I’ll use it again if I ever have a good, simple idea. For my bad, complex ideas I’ll continue building my own framework ;-)


As an update, it appears you can use almost any Python modules in your code as long as you add them into your project folder (either copy the package or if you use a symlink it will copy them automatically). That would mean that everything hinges on their storage. Sessions and deployment are excellent, and everything except for the model you can do yourself. If their storage is easy to use with potential longterm power, then it could big, and a serious choice for hosting major sites.

The only other issue would be one of branding. As the login makes it clear that you are using a Google AppEngine, I don’t see big companies using it. That’s a good thing as it gives us open minded charities a leg up on the over-resourced private sector.

2 Comments »

I think I understand WSGI

I’ve been messing around with Python web frameworks for a quite a while now. Trying out lots of different ones and seeing which one feels like the best fit. As I’ve got closer and closer to the right one, I’ve also found that i am getting closer and closer to using WSGI.

WSGI seems excellent and could be great for Python. Frameworks tend to make things seem more difficult and mysterious than they really are. What has taken me a long time to learn is that WSGI is really very simple.

At it’s simplest there are three aspects to it:

  • You receive a dictionary with useful information in it (environ)
  • You receive a function to call that starts the response (start_response)
  • You return an iterator (ie a list) of strings (this is your page body)

Anything on top of that is just helpers. Helpers are great, but you don’t need a framework that hides what is really going on, when it’s as simple as that.

You can create a hello world app as simple as:

def app(environ, start_response):
    start_response('200 OK', [('content-type', 'text/html')])
    return ["Hello World"]

Obviously that just returns Hello World with no html. Which is bad. So:

def app(environ, start_response):
    start_response('200 OK', [('content-type', 'text/html')])
    begin_body = "<html><body>"
    body = "Hello World"
    end_body = "</body></html>"
    return [begin_body, body, end_body]

We don’t want to write begin_body and end_body every time, so lets write a function to handle this for us:

def put_in_body(args):
    begin_body = "<html><body>"
    end_body = "</body></html>"
    return [begin_body] + list(args) + [end_body]

Then we can just:

def app(environ, start_response):
    start_response('200 OK', [('content-type', 'text/html')])
    return put_in_body("Hello World")

We’re going to want to be able to do lots of different things, and we don’t want to write them all in the body of one function, so let’s write a dispatcher:

def dispatch(environ):
    # We need to get the path from the environ, and work out where to go.
    path_info = environ.get('PATH_INFO', '')
    if path_info == "/goodbye":
        return goodbye(environ)
    else:
        return hello_world(environ)

def hello_world(environ): return ["Hello World"]

def goodbye(environ): return ["Goodbye World"]

def app(environ, start_response): start_response('200 OK', [('content-type', 'text/html')]) return put_in_body(dispatch(environ))

Now if you go to /goodbye it will say “Goodbye World”, otherwise it will say “Hello World”.

As you can see it is all very straightforward. It allows you to do things however you want. Adding more and more functionality is just a case of adding functions that returns strings, and telling the dispatcher when to call that function.

In a later post I’ll talk about threading. It turns out that’s easy as well.

If you want to run the code above, just easy_install paste and then add this to the bottom of your file (which I called wsgi_sample.py):

if name == 'main':
    from paste import httpserver
    httpserver.serve(app, host='127.0.0.1', port='8080')

Then you can do python wsgi_sample.py and visit http://localhost:8080 to see it working (don’t forget to visit http://localhost:8080/goodbye before you leave).

No Comments »

Rest In Python Web Framework

Stumbled across an interesting web framework called RIP, by Luke Arno. It seems to be made up of pieces he’s all made himself.

Going through the obligatory quick wiki example, I like the style of it. Straightforward, obvious, no magic (one of his stated aims). It’s only 0.1 at the moment but I’m going to keep an eye on it; maybe steal some bits.

It does use a very frameworky style. It has a command-line tool that generates loads of boilerplate for you (just like TurboGears). Not keen on that as a style. Having played with web.py and Arc recently, I really like the idea of starting with a single blank file and adding in what you need from there, rather than starting with a large number of files. (It’s possibly no coincidnce that both of those have some sort of link back to Paul Graham).

No Comments »

WP Login