Python 2.7 has reached end of supportand will bedeprecatedon January 31, 2026. After deprecation, you won't be able to deploy Python 2.7applications, even if your organization previously used an organization policy tore-enable deployments of legacy runtimes. Your existing Python2.7 applications will continue to run and receive traffic after theirdeprecation date. We recommend thatyoumigrate to the latest supported version of Python.

Memcache Examples

This page provides Python code examples for usingmemcache. Memcache is a high-performance, distributed memory objectcaching system that provides fast access to cached data. To learn more about memcache, read theMemcache Overview.

This page describes how to use the legacy bundled services and APIs. This API can only run in first-generation runtimes in the App Engine standard environment. If you are updating to the App Engine Python 3 runtime, refer to themigration guide to learn about your migration options for legacy bundled services.

The memcache Pattern

Memcache is typically used with the following pattern:

  • The application receives a query from the user or the application.
  • The application checks whether the data needed to satisfy that query is in memcache.
    • If the data is in memcache, the application uses that data.
    • If the data is not in memcache, the application queries the Datastore and stores the results in memcache for future requests.

The pseudocode below represents a typical memcache request:

defget_data():data=memcache.get('key')ifdataisnotNone:returndataelse:data=query_for_data()memcache.add('key',data,60)returndata

ndb internally uses memcache to speed up queries. However, if you wish, you can alsoexplicitly add memcache calls to gain more control about the speed-ups.

Caching data

The following example demonstrates several ways to set values in memcache usingthe Python API.

# Add a value if it doesn't exist in the cache# with a cache expiration of 1 hour.memcache.add(key="weather_USA_98105",value="raining",time=3600)# Set several values, overwriting any existing values for these keys.memcache.set_multi({"USA_98115":"cloudy","USA_94105":"foggy","USA_94043":"sunny"},key_prefix="weather_",time=3600)# Atomically increment an integer value.memcache.set(key="counter",value=0)memcache.incr("counter")memcache.incr("counter")memcache.incr("counter")

To learn more about theadd(),set_multi(), andset() methods, see thememcache Python API documentation.

Note: The standard Pythonpicklemodule is used to auto pickle and depickle data moved into and out of memcache.

Modifyingguestbook.py to use memcache

TheGuestbook applicationqueries the Datastore on every request (via ndb, so it already gains some of the memcachespeed-ups). You can modify the Guestbook application to usememcache explicitly before resorting to querying the Datastore.

First we'll import the memcache module and create the method that checks memcache before running a query.

defget_greetings(self,guestbook_name):"""    get_greetings()    Checks the cache to see if there are cached greetings.    If not, call render_greetings and set the cache    Args:      guestbook_name: Guestbook entity group key (string).    Returns:      A string of HTML containing greetings.    """greetings=memcache.get('{}:greetings'.format(guestbook_name))ifgreetingsisNone:greetings=self.render_greetings(guestbook_name)try:added=memcache.add('{}:greetings'.format(guestbook_name),greetings,10)ifnotadded:logging.error('Memcache set failed.')exceptValueError:logging.error('Memcache set failed - data larger than 1MB')returngreetings

Next we'll separate out the querying and creation of the HTML for the page. When we don't hit the cache, we'll call this method to query the Datastore and build the HTML string that we'll store in memcache.

defrender_greetings(self,guestbook_name):"""    render_greetings()    Queries the database for greetings, iterate through the    results and create the HTML.    Args:      guestbook_name: Guestbook entity group key (string).    Returns:      A string of HTML containing greetings    """greetings=ndb.gql('SELECT * ''FROM Greeting ''WHERE ANCESTOR IS :1 ''ORDER BY date DESC LIMIT 10',guestbook_key(guestbook_name))output=cStringIO.StringIO()forgreetingingreetings:ifgreeting.author:output.write('<b>{}</b> wrote:'.format(greeting.author))else:output.write('An anonymous person wrote:')output.write('<blockquote>{}</blockquote>'.format(cgi.escape(greeting.content)))returnoutput.getvalue()

Finally we will update theMainPage handler to call the get_greetings() method and display some stats about the number of times the cache was hit or missed.

importcgiimportcStringIOimportloggingimporturllibfromgoogle.appengine.apiimportmemcachefromgoogle.appengine.apiimportusersfromgoogle.appengine.extimportndbimportwebapp2classGreeting(ndb.Model):"""Models an individual Guestbook entry with author, content, and date."""author=ndb.StringProperty()content=ndb.StringProperty()date=ndb.DateTimeProperty(auto_now_add=True)defguestbook_key(guestbook_name=None):"""Constructs a Datastore key for a Guestbook entity with guestbook_name"""returnndb.Key('Guestbook',guestbook_nameor'default_guestbook')classMainPage(webapp2.RequestHandler):defget(self):self.response.out.write('<html><body>')guestbook_name=self.request.get('guestbook_name')greetings=self.get_greetings(guestbook_name)stats=memcache.get_stats()self.response.write('<b>Cache Hits:{}</b><br>'.format(stats['hits']))self.response.write('<b>Cache Misses:{}</b><br><br>'.format(stats['misses']))self.response.write(greetings)self.response.write("""          <form action="/sign?{}" method="post">            <div><textarea name="content" rows="3" cols="60"></textarea></div>            <div><input type="submit" value="Sign Guestbook"></div>          </form>          <hr>          <form>Guestbook name: <input value="{}" name="guestbook_name">          <input type="submit" value="switch"></form>        </body>      </html>""".format(urllib.urlencode({'guestbook_name':guestbook_name}),cgi.escape(guestbook_name)))defget_greetings(self,guestbook_name):"""        get_greetings()        Checks the cache to see if there are cached greetings.        If not, call render_greetings and set the cache        Args:          guestbook_name: Guestbook entity group key (string).        Returns:          A string of HTML containing greetings.        """greetings=memcache.get('{}:greetings'.format(guestbook_name))ifgreetingsisNone:greetings=self.render_greetings(guestbook_name)try:added=memcache.add('{}:greetings'.format(guestbook_name),greetings,10)ifnotadded:logging.error('Memcache set failed.')exceptValueError:logging.error('Memcache set failed - data larger than 1MB')returngreetingsdefrender_greetings(self,guestbook_name):"""        render_greetings()        Queries the database for greetings, iterate through the        results and create the HTML.        Args:          guestbook_name: Guestbook entity group key (string).        Returns:          A string of HTML containing greetings        """greetings=ndb.gql('SELECT * ''FROM Greeting ''WHERE ANCESTOR IS :1 ''ORDER BY date DESC LIMIT 10',guestbook_key(guestbook_name))output=cStringIO.StringIO()forgreetingingreetings:ifgreeting.author:output.write('<b>{}</b> wrote:'.format(greeting.author))else:output.write('An anonymous person wrote:')output.write('<blockquote>{}</blockquote>'.format(cgi.escape(greeting.content)))returnoutput.getvalue()classGuestbook(webapp2.RequestHandler):defpost(self):# We set the same parent key on the 'Greeting' to ensure each greeting# is in the same entity group. Queries across the single entity group# are strongly consistent. However, the write rate to a single entity# group is limited to ~1/second.guestbook_name=self.request.get('guestbook_name')greeting=Greeting(parent=guestbook_key(guestbook_name))ifusers.get_current_user():greeting.author=users.get_current_user().nickname()greeting.content=self.request.get('content')greeting.put()memcache.delete('{}:greetings'.format(guestbook_name))self.redirect('/?'+urllib.urlencode({'guestbook_name':guestbook_name}))app=webapp2.WSGIApplication([('/',MainPage),('/sign',Guestbook)],debug=True)

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-12-15 UTC.