PyGAE
PyGAE

Reputation: 51

Python error on GAE with Memcache - TypeError: unhashable type: 'list'

I have a small Python app that produces a form, the user enters some strings in and it collects them as an array and adds (or tries to) that array as a value of a key in Google's Memcache.

This is the script:

import webapp2
from google.appengine.api import memcache


MAIN_PAGE_HTML = """\
<html>
  <body>
    <form action="/get" method="post">
      <div><input name="ID"/></div>
      <div><input name="param1"/></div>
      <div><input name="param2"/></div>
      <div><input name="param3"/></div>
      <div><input name="param4"/></div>
      <div><input name="param5"/></div>
      <div><input type="submit" value="Change Status"></div>
    </form>
  </body>
</html>
"""

class MainPage(webapp2.RequestHandler):
    def get(self):
        self.response.write(MAIN_PAGE_HTML)

class status(webapp2.RequestHandler):
    def post(self):
        paramarray= (self.request.get_all('param1'),
                     self.request.get_all('param2'),
                     self.request.get_all('param3'),
                     self.request.get_all('param4'),
                     self.request.get_all('param5'))
        array1 = tuple(paramarray)

        memcache.add(key=(self.request.get_all('ID')), value=array1, time=3600)


app = webapp2.WSGIApplication([
    ('/', MainPage),
    ('/get', status),
], debug=True)

I've tried setting paramarray as a tuple, not a list. Still getting the same error:

Traceback (most recent call last):
  File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1535, in __call__
    rv = self.handle_exception(request, response, e)
  File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1529, in __call__
    rv = self.router.dispatch(request, response)
  File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher
    return route.handler_adapter(request, response)
  File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1102, in __call__
    return handler.dispatch()
  File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 572, in dispatch
    return self.handle_exception(e, self.app.debug)
  File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 570, in dispatch
    return method(*args, **kwargs)
  File "/base/data/home/apps/s~gtech-iot/1.391041688070473184/main.py", line 41, in post
    memcache.add(key=(self.request.get_all('ID')), value=array1, time=3600)
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/api/memcache/__init__.py", line 785, in add
    namespace=namespace)
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/api/memcache/__init__.py", line 868, in _set_with_policy
    rpc = self._set_multi_async_with_policy(policy, {key: value},
TypeError: unhashable type: 'list'

Tried to set curly braces, regular, squared, with or without the array1=.. statement

Please help, Thanks

Upvotes: 0

Views: 100

Answers (2)

pgiecek
pgiecek

Reputation: 8240

The problem is not with the value (array1) you are storing into Memcache but rather with the key. You cannot use a value of type list as a key. Check Python Memcache API documentaion.

Any method that takes a ‘key’ argument will accept that key as a string (unicode or not) or a tuple of (hash_value, string) where the hash_value, normally used for sharding onto a memcache instance, is instead ignored, as Google App Engine deals with the sharding transparently.

Upvotes: 1

Dan Cornilescu
Dan Cornilescu

Reputation: 39834

You're passing a list - returned by self.request.get_all('ID') as the key argument to memcache.add(), which is not OK.

I'd suggest some sanity checking of the key - you want it to be at least a non-empty string to make some sense as a memcache key.

If indeed you have multiple possible 'ID' values in the request maybe concatenate them in a string (I'd still question the usability since it's not guaranteed they'd be returned in the same order at the next request) and if not then maybe use self.request.get('ID') instead - it won't return a list like self.request.get_all('ID').

Upvotes: 1

Related Questions