Google App Engine Python scripting

Command line GAE

I am going to rely on the setup described in one of my previous posts. Not everything is needed – just the basic setup: * Google App Engine SDK for Python, * Application based on google-app-engine-django, * csvup sample from the above post.

Say you have some model in your app. I will use csvup.models.Person for this example. I had a need a few times before to make a simple Python command-line based applications that would rely on things provided by GAE. This allows for doing some of the things you can do in your views, but without the need to manually start the dev server and point your browser or use hacks like curl just to initiate the view action.

This is very simple with google-app-engine-django. All the code needed is actually provided in main.py file in the root of the distribution and boils down to this:

from appengine_django import InstallAppengineHelperForDjango
InstallAppengineHelperForDjango()

from csvup.models import Person

for p in Person.all():
  print p

This will initialize the helper and display all the Person instances currently in your production datastore. Neat.

LoadSdk

If you, for some reason, need to access GAE SDK code, you would not be able to do that before you call InstallAppengineHelperForDjango(). That can be a problem, as we will soon determine. There’s a handy function for that, too:

from appengine_django import LoadSdk
LoadSdk()

This will initialize the SDK itself (e.g. set up the paths to it based on the .google_appengine symlink you created), so you can import google.appengine packages.

Using your own datastore

Why is LoadSdk important? Because you can do this:

from appengine_django import LoadSdk
LoadSdk()

from google.appengine.tools import dev_appserver_main as dae
da = dae.DEFAULT_ARGS
da[dae.ARG_DATASTORE_PATH] = '/tmp/my-datastore-path.datastore'

from appengine_django import InstallAppengineHelperForDjango
InstallAppengineHelperForDjango()

from csvup.models import Person
from datetime import date

Person(name='John', birthdate=date.today(), countriesVisitedCount=3, everMarried=True).save()
for p in Person.all():
  print p
print 'done'

Digging inside the GAE helper, you can see that is was made from the manage.py perspective, quite reasonable and expected. This, however, restricts its use, as manage.py doesn’t have all the options that “original” dev_appserver.py provides (have a peek here). There are some bugs, like this one, that reflect this feature.

For some of these, it uses the default arguments specified in GAE SDK’s google/appengine/tools/dev_appserver_main.py. If you take a look, you will find out there is a dict called DEFAULT_ARGS, containing some settings that you might consider changing to suit your needs. This is exactly what the above code does – it changes the datastore path. This can be useful if your script does some destructive operations on the datastore which warrant a separate datastore file just for it.