34

I am storing a list in Redis like this:

redis.lpush('foo', [1,2,3,4,5,6,7,8,9])

And then I get the list back like this:

redis.lrange('foo', 0, -1)

and I get something like this:

[b'[1, 2, 3, 4, 5, 6, 7, 8, 9]']

How can I convert this to actual Python list?

Also, I don't see anything defined in RESPONSE_CALLBACKS that can help? Am I missing something?

A possible solution (which in my opinion sucks) can be:

result = redis.lrange('foo',0, -1)[0].decode()

result = result.strip('[]')

result = result.split(', ')

# lastly, if you know all your items in the list are integers
result = [int(x) for x in result]

UPDATE

Ok, so I got the solution.

Actually, the lpush function expects all the list items be passed as arguments and NOT as a single list. The function signature from redis-py source makes it clear...

def lpush(self, name, *values):
    "Push ``values`` onto the head of the list ``name``"
    return self.execute_command('LPUSH', name, *values)

What I am doing above is send a single list as an argument, which is then sent to redis as a SINGLE item.

I should be unpacking the list instead as suggested in the answer:

redis.lpush('foo', *[1,2,3,4,5,6,7,8,9])

which returns the result I expect...

redis.lrange('foo', 0, -1)
[b'9', b'8', b'7', b'6', b'5', b'4', b'3', b'2', b'1']
treecoder
  • 43,129
  • 22
  • 67
  • 91

3 Answers3

34

I think you're bumping into semantics which are similar to the distinction between list.append() and list.extend(). I know that this works for me:

myredis.lpush('foo', *[1,2,3,4])

... note the * (map-over) operator prefixing the list!

Jim Dennis
  • 17,054
  • 13
  • 68
  • 116
  • Right, it's the difference between lpush() being passed two arguments (key and a single object which happens to be a list) and being passed "n+1" objects (key and each of the object *from within* the list). This is "var args" or "n-ary" behavior in Python. For the built-in list type we'd use "extend()" rather than "append()." – Jim Dennis Apr 06 '13 at 11:34
4

Another way: you can use RedisWorks library.

pip install redisworks

>>> from redisworks import Root
>>> root = Root()
>>> root.foo = [1,2,3,4,5,6,7,8,9]  # saves it to Redis as a list
...
>>> print(root.foo)  # loads it from Redis later

It converts python types to Redis types and vice-versa. So even if you had nested list, it would have worked:

>>> root.sides = [10, [1, 2]]  # saves it as list in Redis.
>>> print(root.sides)  # loads it from Redis
[10, [1, 2]]
>>> type(root.sides[1])
<class 'list'>

Disclaimer: I wrote the library. Here is the code: https://github.com/seperman/redisworks

Seperman
  • 4,254
  • 1
  • 28
  • 27
-1
import json
r = [b'[1, 2, 3, 4, 5, 6, 7, 8, 9]']
rstr = r[0]
res_list = json.loads(rstr)
Yarkee
  • 9,086
  • 5
  • 28
  • 29
  • This response makes no sense. He's using Redis lists with *PUSH and LRANGE Redis operations. JSON encoding a Python option would only make sense for using Redis scalar type with SET and other such operations. He'd look the coherency provided by Redis for *POP and related operations on elements of the list; and be forced to SET and GET the whole list with each operation. – Jim Dennis Nov 12 '14 at 01:01
  • sometimes its better to be specific. – ashim888 Feb 18 '16 at 05:24