【问题标题】:Save unicode in redis but fetch error在redis中保存unicode但获取错误
【发布时间】:2012-05-15 10:48:54
【问题描述】:

我用的是mongodb和redis,redis是我的缓存。

我正在使用 redis-py 缓存 mongodb 对象:

obj in mongodb: {u'name': u'match', u'section_title': u'\u6d3b\u52a8', u'title': 
u'\u6bd4\u8d5b', u'section_id': 1, u'_id': ObjectId('4fb1ed859b10ed2041000001'), u'id': 1}

使用 hgetall(key, obj) 从 redis 获取的 obj 是:

{'name': 'match', 'title': '\xe6\xaf\x94\xe8\xb5\x9b', 'section_title': 
'\xe6\xb4\xbb\xe5\x8a\xa8', 'section_id': '1', '_id': '4fb1ed859b10ed2041000001', 'id': '1'}

如您所见,从缓存中获取的 obj 是 str 而不是 unicode,因此在我的应用程序中,出现如下错误:'ascii' codec can't decode byte 0xe6 in position 12: ordinal not in range(128)

谁能给点建议?谢谢你

【问题讨论】:

  • 以及如何在redis中保存mongodb对象?

标签: python redis


【解决方案1】:

我想我已经发现了问题所在。读完这篇文章后,我不得不从 redis 显式解码,这很痛苦,但有效。

我偶然发现了一篇博文,其中作者的输出都是 unicode 字符串,这与我的 obv 不同。

查看StrictRedis.__init__ 有一个参数decode_responses,默认为Falsehttps://github.com/andymccurdy/redis-py/blob/273a47e299a499ed0053b8b90966dc2124504983/redis/client.py#L446

在构造上传递decode_responses=True,对我来说这修复了操作问题。

【讨论】:

  • 谢谢,我稍后再试。这可能是最好的解决方案,因为我不会弄乱我的代码。
【解决方案2】:

更新,对于全局设置,请检查jmoz's answer

如果您使用第三方库,例如django-redis,您可能需要指定自定义的ConnectionFactory

class DecodeConnectionFactory(redis_cache.pool.ConnectionFactory):
    def get_connection(self, params):
        params['decode_responses'] = True
        return super(DecodeConnectionFactory, self).get_connection(self, params)

假设你使用redis-py,你最好将str而不是unicode传递给Redis,否则Redis will encode it automatically用于*set命令,通常是in UTF-8。对于*get 命令,Redis 不知道值的形式类型,只需要直接返回str 中的值。

因此,正如 Denis 所说,将对象存储到 Redis 的方式至关重要。您需要将值转换为 str 以使 Redis 层对您透明。

另外,set the default encoding to UTF-8 而不是使用ascii

【讨论】:

  • 为什么他们会自动对其进行编码,然后在 get 上留下一个字符串?
  • @jmoz 我不确定,也许作者知道原因 =p 。但与 psycopg2 等适配器不同,通常 redis-py 客户端不会存储带有数据的原始数据类型。因此,无法确切知道数据(字符串)最初是什么类型以及如何对其进行解码。也许坚持str 而不是接受其他类型的值然后将它们隐式转换为str 更好,但谁知道呢。
  • @okm 前几天我发现了一些关于此的内容,请查看我的答案。
  • 我启用了这个设置,现在当我尝试在 Django 的缓存中存储和检索字典时,似乎得到了UnicodeDecodeError
【解决方案3】:

对于每个字符串,您可以使用decode 函数将其转换为 utf-8,例如如果代码中的标题字段的值:

In [7]: a='\xe6\xaf\x94\xe8\xb5\x9b'

In [8]: a.decode('utf8')
Out[8]: u'\u6bd4\u8d5b'

【讨论】:

  • 伙计,我想你想让缓存不是为了解码-编码的乐趣,而是为了增加他的系统。
【解决方案4】:

我建议您在写入 MongoDB 或 Redis(或任何外部系统)之前始终编码为 utf-8。并且当你得到结果时你解码('utf-8'),这样你就可以在 Python 中使用 Unicode。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-29
    相关资源
    最近更新 更多