Building on the Google App Engine

Last week Google announced its Google App Engine, a hosting service that makes it very easy to write interesting web applications that run on Google’s servers. To try it myself, I decided to write a small photoblogging application. The result is here. It uses Nu on the client side to capture pictures from an Apple camera and automatically uploads them to my web application, which is written in Python and running on the Google App Engine.

Here are some first impressions from working with the App Engine. It’s not an introduction to the App Engine; for that see Google’s site and many other blog posts. Instead, it’s part wisdom, part rant. Ready?

Although it’s nice to have a development server that runs locally, mirroring data between development and production servers is difficult (currently there don’t seem to be any tools for this).

If you only run your app on the production server, it’s likely to fail mysteriously when you add new queries or filters; that’s because these require indices that are created automatically when you run on the development server. That development run also writes an index.yml file that is read by the production server. The production server reads this file and creates the indices listed in it, but if the index you need isn’t listed there, the production server won’t create it. Then when you run a query that needs a missing index, your action will fail with an unhelpful error message.

Page templates are written in the Django template language, which is completely different from the Python used to implement GAE applications. That will be a shock to a Rubyist and an annoyance to people who are picking up Python and the template language at the same time. While some people seem to prefer this forced separation of logic and templates, I think you could be just as organized without forcing a second language into the mix, although Python’s whitespace sensitivity would make it a bad choice for a template language. So are Pythonistas simply turning a flaw into a feature? I think so.

Along those same lines, explicitly passing template parameters in hashes seems tedious, although again, “bondage-and-discipline” programmers will probably say that’s a feature.

If you’re just getting back into Python, be careful of its sensitivity to tabs. If your editor is inserting tabs and assuming a different tab width than Python, your code will fail messily. I found it best to just turn off tabs altogether by telling TextMate to use “soft spaces” (look for the “Tabs” popup at the bottom of the document window).

As someone who has now throughly spoiled himself with Lisp, I’m especially sensitive to the Python anachronisms that clutter my code. For example, to declare the attributes associated with my Photo objects, I wrote the following Python:

class Photo(db.Model):
  name = db.StringProperty()
  data = db.BlobProperty()    
  user = db.UserProperty()
  description = db.TextProperty()
  location = db.StringProperty()
  created = db.DateTimeProperty(auto_now_add=True)
  updated = db.DateTimeProperty(auto_now=True)

All that syntax! It seems much preferable to me to simply write the following:

(object-class Photo
   ;; (name type options...)
   (name string)
   (data blob)
   (user user)
   (description text)
   (location string)
   (created date auto_now_add)
   (created date auto_now))

Similarly, it seems needlessly verbose to write classes for action handlers and then have to declare them again somewhere else in the code so that they can be used. For example, here’s the action to display a photo:

class PhotoAction(webapp.RequestHandler):
  def get(self):
    id = self.request.get('id') 
    photo = Photo.get_by_id(int(id))
    self.response.headers['Content-Type'] = 'image/jpeg'
    self.response.out.write(photo.data)

But that won’t get called unless you explicitly install it in the server like this:

  application = webapp.WSGIApplication([
    ...
    ('/photo', PhotoAction),
    ...
  ], debug=_DEBUG)

Very non-DRY. To me, Blake Mizerany’s Sinatra project gets it right.

The ellipses above are in place of other action handlers. As a Lisper/Nubie, I found myself frequently forgetting to put commas between them, another language anachronism that seems completely superflous.

The programming environment itself is limited by design to keep applications from interfering with their containers. For this little project, it would have been very helpful to have the Python Imaging Library or something similar available for server-side image processing. For now, it’s not there, but it’s probably high on Google’s todo list.

The deployment process is very easy, but nothing that you couldn’t automate yourself with a tool like Rake/Capistrano or nuke.

The app engine includes a user abstraction that lets people log into your site using their Google accounts (without giving you their passwords). This is a big benefit, and seems much simpler than implementing OpenID or your own user id system.

I can’t say anything about scalability, but most of us assume that it’s there.

The potential for commoditization is the biggest draw here. Already, people have begun setting up alternate hosting capabilities, like this one. I expect we’ll see a lot of those now, even if Google decides not to put much more effort into this project.

But I think that’s unlikely. Google’s App Engine is a great idea, and although the details will surely change with time, from now on the process of writing hosted web applications will be a lot simpler.

One comment ↓

#1Jon on 2008-04-18 at 04:11:58 America/Los_Angeles

You certainly don’t need to use the Django templates (I hate them too). I use Mako: http://www.makotemplates.org/

The release version doesn’t work in GAE yet, but the svn trunk does.

Leave a Comment (sign in with Twitter)