How to store and retrieve a dictionary with redis

# I have the dictionary my_dict
my_dict = {
'var1' : 5
'var2' : 9
}
r = redis.StrictRedis()

How would I store my_dict and retrieve it with redis. For example, the following code does not work.

#Code that doesn't work
r.set('this_dict', my_dict)  # to store my_dict in this_dict
r.get('this_dict')  # to retrieve my_dict
158892 次浏览

Redis SET 命令存储字符串,而不是任意数据。您可以尝试使用 redis HSET 命令将 dict 存储为 redis 散列,如下所示

for k,v in my_dict.iteritems():
r.hset('my_dict', k, v)

但 redis 数据类型和 python 数据类型并不完全一致。Python dicts 可以任意嵌套,但 redis 散列将要求您的值是一个字符串。您可以采取的另一种方法是将 python 数据转换为字符串并将其存储在 redis 中,类似于

r.set('this_dict', str(my_dict))

然后,当您取出字符串时,您需要解析它来重新创建 python 对象。

你可以腌制你的字典,并保存为字符串。

import pickle
import redis


r = redis.StrictRedis('localhost')
mydict = {1:2,2:3,3:4}
p_mydict = pickle.dumps(mydict)
r.set('mydict',p_mydict)


read_dict = r.get('mydict')
yourdict = pickle.loads(read_dict)

您可以通过 hmset来完成(可以使用 hmset设置多个键)。

hmset("RedisKey", dictionaryToSet)

import redis
conn = redis.Redis('localhost')


user = {"Name":"Pradeep", "Company":"SCTL", "Address":"Mumbai", "Location":"RCP"}


conn.hmset("pythonDict", user)


conn.hgetall("pythonDict")


{'Company': 'SCTL', 'Address': 'Mumbai', 'Location': 'RCP', 'Name': 'Pradeep'}

另一种方法: 您可以使用 RedisWorks库。

pip install redisworks

>>> from redisworks import Root
>>> root = Root()
>>> root.something = {1:"a", "b": {2: 2}}  # saves it as Hash type in Redis
...
>>> print(root.something)  # loads it from Redis
{'b': {2: 2}, 1: 'a'}
>>> root.something['b'][2]
2

它将 python 类型转换为 Redis 类型,反之亦然。

>>> 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

如果您想在 redis 中存储一个 python dict,最好将其存储为 json 字符串。

import json
import redis


r = redis.StrictRedis(host='localhost', port=6379, db=0)
mydict = { 'var1' : 5, 'var2' : 9, 'var3': [1, 5, 9] }
rval = json.dumps(mydict)
r.set('key1', rval)

同时使用 json.load 检索反序列化它

data = r.get('key1')
result = json.loads(data)
arr = result['var3']

那么没有被 json 函数序列化的类型(eg.byte)呢?

You can write encoder/decoder functions for types that cannot be serialized by json functions. eg. writing base64/ascii encoder/decoder function for byte array.

正如其他人已经给出的基本答案一样,我想补充一些内容。

以下是使用 HashMap/Dictionary/Mapping类型值执行基本操作的 REDIS命令。

  1. 返回传递的单个密钥的值
  2. 对于单个键,HSET = > set/update 值
  3. HMGET => Returns value for single/multiple keys passed
  4. HMSET = > set/update 多个键的值
  5. 返回映射中的所有(键,值)对。

以下是 redis-py库中它们各自的方法:-

  1. HGET = > HGET
  2. HSET = > HSET
  3. HMGET = > HMGET
  4. HMSET = > HMSET
  5. [翻译]

如果映射不存在,上述所有 setter 方法都会创建映射。 如果映射中的映射/键不存在,则上述所有 getter 方法都不会引发错误/异常。

Example:
=======
In [98]: import redis
In [99]: conn = redis.Redis('localhost')


In [100]: user = {"Name":"Pradeep", "Company":"SCTL", "Address":"Mumbai", "Location":"RCP"}


In [101]: con.hmset("pythonDict", {"Location": "Ahmedabad"})
Out[101]: True


In [102]: con.hgetall("pythonDict")
Out[102]:
{b'Address': b'Mumbai',
b'Company': b'SCTL',
b'Last Name': b'Rajpurohit',
b'Location': b'Ahmedabad',
b'Name': b'Mangu Singh'}


In [103]: con.hmset("pythonDict", {"Location": "Ahmedabad", "Company": ["A/C Pri
...: sm", "ECW", "Musikaar"]})
Out[103]: True


In [104]: con.hgetall("pythonDict")
Out[104]:
{b'Address': b'Mumbai',
b'Company': b"['A/C Prism', 'ECW', 'Musikaar']",
b'Last Name': b'Rajpurohit',
b'Location': b'Ahmedabad',
b'Name': b'Mangu Singh'}


In [105]: con.hget("pythonDict", "Name")
Out[105]: b'Mangu Singh'


In [106]: con.hmget("pythonDict", "Name", "Location")
Out[106]: [b'Mangu Singh', b'Ahmedabad']

我希望这能让事情变得更清楚。

Try rejson-py which is relatively new since 2017. Look at this 介绍.

from rejson import Client, Path


rj = Client(host='localhost', port=6379)


# Set the key `obj` to some object
obj = {
'answer': 42,
'arr': [None, True, 3.14],
'truth': {
'coord': 'out there'
}
}
rj.jsonset('obj', Path.rootPath(), obj)


# Get something
print 'Is there anybody... {}?'.format(
rj.jsonget('obj', Path('.truth.coord'))
)


# Delete something (or perhaps nothing), append something and pop it
rj.jsondel('obj', Path('.arr[0]'))
rj.jsonarrappend('obj', Path('.arr'), 'something')
print '{} popped!'.format(rj.jsonarrpop('obj', Path('.arr')))


# Update something else
rj.jsonset('obj', Path('.answer'), 2.17)

你可以用另一种方式来处理这个问题:

import redis
conn = redis.Redis('localhost')


v={'class':'user','grants': 0, 'nome': 'Roberto', 'cognome': 'Brunialti'}


y=str(v)
print(y['nome']) #<=== this return an error as y is actually a string
conn.set('test',y)


z=eval(conn.get('test'))
print(z['nome']) #<=== this really works!

我没有测试它的效率/速度。

If you don't know exactly how to organize data in Redis, I did some performance tests, including the results parsing. 我使用的字典(D)有437.084个键(md5格式) ,以及这个表单的值:

{"path": "G:\tests\2687.3575.json",
"info": {"f": "foo", "b": "bar"},
"score": 2.5}

First Test (将数据插入到 redis 键值映射中) :

conn.hmset('my_dict', d)  # 437.084 keys added in 8.98s


conn.info()['used_memory_human']  # 166.94 Mb


for key in d:
json.loads(conn.hget('my_dict', key).decode('utf-8').replace("'", '"'))
#  41.1 s


import ast
for key in d:
ast.literal_eval(conn.hget('my_dict', key).decode('utf-8'))
#  1min 3s


conn.delete('my_dict')  # 526 ms

Second Test (将数据直接插入到 Redis 键中) :

for key in d:
conn.hmset(key, d[key])  # 437.084 keys added in 1min 20s


conn.info()['used_memory_human']  # 326.22 Mb


for key in d:
json.loads(conn.hgetall(key)[b'info'].decode('utf-8').replace("'", '"'))
#  1min 11s


for key in d:
conn.delete(key)
#  37.3s

正如您所看到的,在第二个测试中,只有“ info”值需要进行解析,因为 hgetall (key)已经返回了一个 dict,但是没有返回嵌套的一个。

当然,使用 Redis 作为 python 命令的最佳例子是 第一次测试

人们可能会考虑使用 信息包,这是由重新编排的背书。

import msgpack


data = {
'one': 'one',
'two': 2,
'three': [1, 2, 3]
}


await redis.set('my-key', msgpack.packb(data))
val = await redis.get('my-key')
print(msgpack.unpackb(val))


# {'one': 'one', 'two': 2, 'three': [1, 2, 3]}

使用 Msgpack-python爱奥瑞迪斯

根据 Redis docs,不推荐使用 HMSET。您现在可以使用 HSET和以下字典:

import redis


r = redis.Redis('localhost')
    

key = "hashexample"
entry = {
"version":"1.2.3",
"tag":"main",
"status":"CREATED",
"timeout":"30"
}
r.hset(key, mapping=entry)

注意: 非常不直观地,如果 hset只是简单地传递给第二个位置(未命名)参数,hset将不接受 dictionary (引发一个错误,表明它不接受 dictionary,参见[1])。您需要将字典传递给 名字参数 mapping=

[1] *** redis.exceptions.DataError: Invalid input of type: 'dict'. Convert to a bytes, string, int or float first.

不推荐使用 Redis.hmset () ,而是使用 Redis.hset ()。

由于不推荐使用 HMSET,因此可以使用 HSET:

import redis


r = redis.Redis(host='localhost', port=6379, decode_responses=True)
r.hset('user:23', mapping={'id': 23, 'name': 'ip'})
r.hgetall('user:23')

在 Nameko (经常使用 redis 后端的 Python 微服务框架)的上下文中,可以使用 hmset 如下:

import uuid
from nameko.rpc import rpc
from nameko_redis import Redis


class AirportsService:
name = "trips_service"
redis = Redis('development')
@rpc
def get(self, trip_id):
trip = self.redis.get(trip_id)
return trip
@rpc
def create(self, airport_from_id, airport_to_id):
trip_id = uuid.uuid4().hex
pyDict = {"from":airport_from_id, "to":airport_to_id}
self.redis.hmset(trip_id, pyDict)
return trip_id