Redis: How to parse a list result
Question:
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']
Answers:
import json
r = [b'[1, 2, 3, 4, 5, 6, 7, 8, 9]']
rstr = r[0]
res_list = json.loads(rstr)
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!
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
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']
import json
r = [b'[1, 2, 3, 4, 5, 6, 7, 8, 9]']
rstr = r[0]
res_list = json.loads(rstr)
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!
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