+1  A: 

Datastore

Use the datastore to hold any long living information. The datastore should be used like you would use a normal database to hold data that will be used in your site/application.

MemCache

Use this to access data a lot quicker than trying to access the datastore. MemCache can return data really quickly and can be used for any data that needs to span multiple calls from users. It is normally data that was originally in the datastore and then moved to the memcache.

def get_data():
  data = memcache.get("key")
  if data is not None:
    return data
  else:
    data = self.query_for_data() #get data from the datastore
    memcache.add("key", data, 60)
    return data

The memcache will flush itself when the item is out of date. You set this in the last param of the add shown above.

Global Variables I wouldn't use these at all since they can't span instances. In GAE a request creates a new instance, well in python it does. If you want to use Global variables I would store the data needed in the memcache.

AutomatedTester
Incorrect: Each request in App Engine does not create a new instance.
Nick Johnson
The way that I read http://code.google.com/appengine/docs/python/tools/webapp/requestclass.html it does. I have never been able to share information between GETs without using memcache or datastore. If you have some code then I would love to see it because I have instances where it would be useful.
AutomatedTester
The `Request` object is always new, yes. However, the global scope of your application is kept "alive" between requests, so that everything doesn't have to be imported again. Try checking if a global variable has a value, and if it doesn't, set it to a random value. Then try printing out its value in your application.
Blixt
+1  A: 

Your post is a good summary of the 3 major options. You mostly have answered the question already. However, if you are currently building an app and stressing over whether or not you should memcache something, try this:

  1. Write your app using the datastore for everything that needs to outlive more than one request.
  2. Once your app (or some usable subset) is working, run some functional tests or simulations to see where the slow spots (or high quota usage) are.
  3. Find the most slow or inefficient request path, and figure out how to make that faster (either by using memcache, or altering your datastructures so you can do gets instead of queries, or possibly storing something in a global instance variable*)
  4. goto 2 until you're satisfied.

*Things that might be good for a "global" variable would be something that is relatively expensive to create/fetch, that a substantial portion of your requests will use, and that does not need to be consistent across requests/users.

Peter Recore
Yup, I've done that already actually... I've got an application up and running that uses only the datastore, and I'm currently having a group of people try it out to see which requests use the most resources. But I created this post partly to help others looking for the same thing, and partly because I am unsure about using global objects (they must use up memory somehow, but not in an as controlled way as memcache; what is the Google policy on large global objects, etc?)
Blixt
+1  A: 

I use global variable to speed up json conversion. Before I convert my data structure to json, I hash it and check if the json if already available. For my app this gives quite a speedup as the pure python implementation is quite slow.

Koen Bok
Ah, nice tip! `=)`
Blixt
+1  A: 

Global variables

To complement AutomatedTester's answer, and also reply his further question about how to share information between GETs without memcache or datastore, below a quick illustration of how to use global variables:

if 'i' not in globals():
    i = 0

def main():
    global i
    i += 1
    print 'Status: 200'
    print 'Content-type: text/plain\n'
    print i

if __name__ == '__main__':
    main()

Calling this script multiple times will give you 1, 2, 3... Of course as mentioned earlier by Blixt you should not count on this trick too much ('i' can sometimes switch back to zero) but it can be useful to store user-specific information in a dictionary, session data for instance.

Louis LC