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

Pic*_*Man 62 python redis

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

我如何存储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
Run Code Online (Sandbox Code Playgroud)

Pra*_*epK 117

你可以做到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'}
Run Code Online (Sandbox Code Playgroud)

  • 如果它是嵌套的数据结构而不是简单的dict,例如包含一些数组等.用`json.dumps()`串行编写你的数据作为字符串,并从redis用户`json.loads()`重新反序后将其反序列化为python数据结构 (33认同)
  • `json.dumps()`和`json.loads()`只有你的字典键永远是字符串才能正常工作.如果你不是那么你可以考虑使用泡菜. (5认同)
  • json与字节不兼容,因此json序列化不是全局解决方案,例如,如果您的字典具有字节值,则此方法将不起作用。 (4认同)
  • 值得注意的是,hmset的文档没有告诉您这一点,但是如果您尝试存储一个空的dict,则会引发DataError。 (3认同)
  • @Pradeep 我们如何使密钥动态化。假设数据每 15 分钟插入一次,那么我如何使密钥动态化 (2认同)
  • 请注意,基础 Redis 命令 `HMSET` 在版本 4.0.0(2017 年 7 月)中[已被弃用](https://redis.io/commands/hmset)(移至不同的函数),但 `redis-py`仍然执行它[在 hmset() 中](https://redis-py.readthedocs.io/en/latest/_modules/redis/client.html#Redis.hmset)。 (2认同)
  • 此方法已被弃用。请改用 hset。但有了新函数 hset。字典不能再用了。 (2认同)

Dav*_*veQ 28

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

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)
Run Code Online (Sandbox Code Playgroud)

  • 请注意,如果与用户输入一起使用,您的服务器[很容易出现远程代码执行](https://davidhamann.de/2020/04/05/exploiting-python-pickle/),则应该使用“pickle.loads”仅用于 100% 可信数据 (5认同)
  • 的确如此,但是根据读写的速度,这可能会增加严重的开销。酸洗操作很慢 (3认同)
  • Pickling 还有一个重要的缺点,即您无法调试 Redis 中存储的数据,因为它们是二进制的。 (2认同)

小智 21

根据Redis 文档, 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)
Run Code Online (Sandbox Code Playgroud)

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

[1] *** redis.exceptions.DataError: Invalid input of type: 'dict'. Convert to a bytes, string, int or float first.
Run Code Online (Sandbox Code Playgroud)


Sep*_*man 14

另一种方式:你可以使用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
Run Code Online (Sandbox Code Playgroud)

它将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'>
Run Code Online (Sandbox Code Playgroud)

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

  • 需要注意的是,如果将变量设置为 dict,RedisWorks 在底层使用了 `hmset`,因此如果你执行 `root.something = {}`,你将得到一个 DataError,因为 `hmset` 不允许空字典。我提到这一点是因为 redis 的文档没有告诉你这一点。 (2认同)

Saj*_*ier 9

如果要在redis中存储python字典,最好将其存储为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)
Run Code Online (Sandbox Code Playgroud)

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

data = r.get('key1')
result = json.loads(data)
arr = result['var3']
Run Code Online (Sandbox Code Playgroud)

没有被json函数序列化的类型(例如字节)呢?

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

  • 对于默认无法编码/解码的类型,您可以编写一个编码器/解码器函数(根据需要,例如base64/ascii编码)。 (2认同)
  • 缺少导入 json。 (2认同)

Jes*_*aur 6

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

for k,v in my_dict.iteritems():
    r.hset('my_dict', k, v)
Run Code Online (Sandbox Code Playgroud)

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

r.set('this_dict', str(my_dict))
Run Code Online (Sandbox Code Playgroud)

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

  • 他可以将数据转换为json并将结果存储在redis中 (2认同)

Man*_*hit 6

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

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

  1. HGET =>返回传递的单个键的值
  2. HSET =>设置/更新单个键的值
  3. HMGET =>返回传递的单个/多个键的值
  4. HMSET =>设置/更新多重键的值
  5. HGETALL =>返回映射中的所有(键,值)对。

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

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

如果不存在映射,则上述所有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']
Run Code Online (Sandbox Code Playgroud)

我希望,这会使事情变得更清楚。


Oha*_*hav 6

可以考虑使用由 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]}
Run Code Online (Sandbox Code Playgroud)

使用msgpack-pythonaioredis