【问题标题】:Python-redis keys() returns list of bytes objects instead of stringsPython-redis keys() 返回字节对象列表而不是字符串
【发布时间】:2017-10-17 00:20:34
【问题描述】:

我正在使用常规的 redis 包来将我的 Python 代码连接到我的 Redis 服务器。

作为我的代码的一部分,我检查我的 Redis 服务器键中是否存在字符串对象。

string = 'abcde'
if string in redis.keys():
  do something..

由于某些原因,redis.keys() 返回一个包含字节对象的列表,例如[b'abcde'],而我的字符串当然是str 对象。

我已经尝试在我的 redis 生成器中设置 charsetencodingdecode_responses,但没有帮助。

我的目标是将数据作为字符串插入前面,而不是遍历键列表并在检查时将每个元素更改为 str()。

谢谢

【问题讨论】:

标签: python redis


【解决方案1】:

您可以将 Redis 客户端配置为使用 decode_responses 参数到 StrictRedis 构造函数自动将响应从字节转换为字符串:

r = redis.StrictRedis('localhost', 6379, charset="utf-8", decode_responses=True)

确保您与客户端之间的charset 选项保持一致。

注意

您最好使用EXISTS 命令并重组您的代码,例如:

string = 'abcde'
if redis.exists(string):
    do something..

KEYS 操作会返回 Redis 数据库中的每个键,会导致生产中的性能严重下降。作为副作用,您可以避免处理二进制到字符串的转换。

【讨论】:

  • 谢谢。如果我需要使用字典键的值怎么办?如何自动将其转换为字符串而不是字节?
  • 我用有关 decode_responses 的信息更新了答案。
  • 再次感谢。我在连接池中使用redis.Redis 尝试了这个,但效果不佳。decode_responses 参数中的StrictRedisredis.Redis 之间有什么区别吗?我在文档中发现他们都应该接受这个论点
  • 添加 decode_responses=True 仅在我将其添加到 ConnectionPool 初始化而不是 StrictRedis 初始化时才对我有用。 connection_pool = redis.ConnectionPool(host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD, decode_responses=True) redis_db = redis.StrictRedis(connection_pool=connection_pool, charset='utf-8')
  • charset=utf-8 错误有两个原因。首先,charset 参数已被弃用,如果您使用它,您将收到警告。它已被 encoding 参数替换。其次,encoding参数默认为utf-8,完全不需要设置。
【解决方案2】:

如果您不希望迭代列表以进行解码,请将您的 redis 连接设置为自动执行解码,您将收到所需的结果。在您的连接字符串中如下所示,请注意 decode_responses 参数:

rdb = redis.StrictRedis(host="localhost", port=6379, db=0, decode_responses=True)

编码愉快! :-) (2019 年 11 月 13 日修订)

【讨论】:

  • 这不起作用。顺便说一句,“字符集”已被弃用。改用“编码”。
  • @zzxwill - 模组制作!
  • 这很酷!虽然我期望的大多数结果都是字符串,但我有一小部分查询想要覆盖此设置并实际获取字节。有没有办法从现有的连接中获得“派生”连接?例如。 rdb2 = rdb.copy(decode_responses=False) 或类似的?
  • 回答我自己的“评论中的问题”...我们可以从kwold = rdb.connection_pool.connection_kwargs 获取当前连接参数,并在修改为kwnew = {**kwold, **kwargs}rdbnew = redis.StrictRedis(**kwnew) 之后建立新连接。
  • 在我之前的评论之后,我现在刚刚发布了这个想法here
【解决方案3】:

一种解决方案可以是:

解码redis键

print(key)
#output is : b'some_key'

print(key.decode())
#output is : 'some_key'

更新:

将字典对象传递给 RedisPost 类,然后解码单个项目并将它们存储为一个对象。

class RedisPost():
   def __init__(self, dic):
      for k,v in dic.items():
          if not isinstance(k,int):
             var = k.decode()
             setattr(self,var,v.decode())


my_dic = {'a':12, 'b':123}
obj = RedisPost(my_dic)
print(obj.a) # output will be 12 

【讨论】:

  • OP 提到他们不想迭代和检查:“而不是迭代键列表并在检查时将每个元素更改为 str()”
【解决方案4】:

以前的答案是正确的,因为需要decode_responses 连接参数才能自动执行此操作,但他们忽略的是,如果使用池进行连接,则需要在 ConnectionPool 上进行设置。下面的 sn-p 会将所有客户端上的 'decode_responses' 值设置为 true,即使客户端在连接期间将自身设置为 False

pool = redis.ConnectionPool(host=REDIS_HOST, port=REDIS_PORT, db=REDIS_DB, password=REDIS_PWD, decode_responses=True)

【讨论】:

  • 您有可以在答案中展示的示例吗? - 你应该 edit 它并包含一个这样人们就知道你的意思了。
  • 您好,我冒昧地删除了您的部分与手头问题无关的答案,回答老问题完全没有问题。
  • 谢谢!添加 decode_responses=True 仅在我将其添加到 ConnectionPool 初始化而不是 StrictRedis 初始化时才对我有用。 connection_pool = redis.ConnectionPool(host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD, decode_responses=True) redis_db = redis.StrictRedis(connection_pool=connection_pool, charset='utf-8')
猜你喜欢
  • 2011-05-13
  • 1970-01-01
  • 2019-03-25
  • 1970-01-01
  • 2017-07-18
  • 2011-07-29
  • 2012-11-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多