Python 如何使用redis存储和检索字典

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32276493/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 11:18:51  来源:igfitidea点击:

How to store and retrieve a dictionary with redis

pythonredis

提问by PiccolMan

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

我将如何存储 my_dict 并使用 redis 检索它。例如,以下代码不起作用。

#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

采纳答案by PradeepK

You can do it by hmset(multiple keys can be set using hmset).

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

hmset("RedisKey", dictionaryToSet)

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

回答by Jesusaur

The redis SET command stores a string, not arbitrary data. You could try using the redis HSET command to store the dict as a redis hash with something like

redis SET 命令存储一个字符串,而不是任意数据。您可以尝试使用 redis HSET 命令将 dict 存储为 redis 哈希,例如

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

but the redis datatypes and python datatypes don't quite line up. Python dicts can be arbitrarily nested, but a redis hash is going to require that your value is a string. Another approach you can take is to convert your python data to string and store that in redis, something like

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

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

and then when you get the string out you will need to parse it to recreate the python object.

然后当你得到字符串时,你需要解析它以重新创建 python 对象。

回答by DaveQ

you can pickle your dict and save as string.

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

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)

回答by Seperman

Another way: you can use RedisWorkslibrary.

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

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

It converts python types to Redis types and vice-versa.

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

免责声明:我编写了库。这是代码:https: //github.com/seperman/redisworks

回答by Saji Xavier

If you want to store a python dict in redis, it is better to store it as json string.

如果要在redis中存储python dict,最好将其存储为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)

While retrieving de-serialize it using json.loads

在使用 json.loads 检索反序列化它时

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

What about types (eg.bytes) that are not serialized by json functions ?

未由 json 函数序列化的类型(例如字节)呢?

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.

您可以为 json 函数无法序列化的类型编写编码器/解码器函数。例如。为字节数组编写 base64/ascii 编码器/解码器函数。

回答by Mangu Singh Rajpurohit

As the basic answer has already give by other people, I would like to add some to it.

由于其他人已经给出了基本答案,我想补充一些。

Following are the commands in REDISto perform basic operations with HashMap/Dictionary/Mappingtype values.

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

  1. HGET => Returns value for single key passed
  2. HSET => set/updates value for the single key
  3. HMGET => Returns value for single/multiple keys passed
  4. HMSET => set/updates values for the multiple key
  5. HGETALL => Returns all the (key, value) pairs in the mapping.
  1. HGET => 返回传递的单个键的值
  2. HSET => 设置/更新单个键的值
  3. HMGET => 返回传递的单个/多个键的值
  4. HMSET => 设置/更新多个键的值
  5. HGETALL => 返回映射中的所有 (key, value) 对。

Following are their respective methods in redis-pylibrary :-

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

  1. HGET => hget
  2. HSET => hset
  3. HMGET => hmget
  4. HMSET => hmset
  5. HGETALL => hgetall
  1. HGET => hget
  2. HSET => hset
  3. HMGET => hmget
  4. HMSET => HMSET
  5. HGETALL => hgetall

All of the above setter methods creates the mapping, if it doesn't exists. All of the above getter methods doesn't raise error/exceptions, if mapping/key in mapping doesn't exists.

如果映射不存在,所有上述 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']

I hope, it makes things more clear.

我希望,它使事情更清楚。

回答by Kevin Zhu

Try rejson-pywhich is relatively new since 2017. Look at this introduction.

尝试自 2017 年以来相对较新的rejson-py。看看这个介绍

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)

回答by roberto

An other way you can approach the matter:

你可以用另一种方式来解决这个问题:

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!

I did not test it for efficiency/speed.

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

回答by Tavy

If you don't know exactly how to organize data in Redis, I did some performance tests, including the results parsing. The dictonary I used (d) had 437.084 keys (md5 format), and the values of this form:

如果你不知道如何在Redis中准确组织数据,我做了一些性能测试,包括结果解析。我使用的字典(d)有 437.084 个键(md5 格式),并且这种形式的值:

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

First Test(inserting data into a redis key-value mapping):

第一次测试(将数据插入到 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(inserting data directly into Redis keys):

第二次测试(直接将数据插入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

As you can see, in the second test, only 'info' values have to be parsed, because the hgetall(key) already returns a dict, but not a nested one.

如您所见,在第二个测试中,只需要解析 'info' 值,因为 hgetall(key) 已经返回了一个 dict,而不是一个嵌套的。

And of course, the best example of using Redis as python's dicts, is the First Test

当然,使用 Redis 作为 python 字典的最好例子是First Test

回答by Ohad Lahav

One might consider using MessagePack which is endorsed by redis.

可以考虑使用由 redis 认可的MessagePack

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

Using msgpack-pythonand aioredis

使用msgpack-pythonaioredis