redis-py and hgetall behavior

Solution 1:

This is the intended behavior. By default, strings coming out of Redis don't get decoded. You have a couple options:

  • Decode the data yourself.
  • Create a client instance with the decode_responses argument, e.g., StrictRedis(decode_responses=True). This will decode all strings that come from Redis based on the charset argument (which defaults to utf-8). Only do this is you're sure every response from Redis has string data that you want decoded to utf-8. If you're using the same client instance to get binary data such as a pickled object, you shouldn't use this option. In that case, I'd suggest using a separate client instance for the binary data.

Source: https://github.com/andymccurdy/redis-py/issues/463#issuecomment-41229918

Solution 2:

POOL = redis.ConnectionPool(host='localhost', **decode_responses=True**, port=6379, db=0)
datastore = redis.StrictRedis(connection_pool=POOL)

if you use the ConnectionPool, you should move the decode_responses=True to the constructor of ConnectionPool.

Solution 3:

Here's a simple routine to perform the byte decoding for the redis dict returned by HGETALL

def decode_redis(src):
    if isinstance(src, list):
        rv = list()
        for key in src:
            rv.append(decode_redis(key))
        return rv
    elif isinstance(src, dict):
        rv = dict()
        for key in src:
            rv[key.decode()] = decode_redis(src[key])
        return rv
    elif isinstance(src, bytes):
        return src.decode()
    else:
        raise Exception("type not handled: " +type(src))

... and to use, just pass it the redis dict ...

obj = decode_redis(redis_connection.hgetall(key))