6

我正在使用 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)

任何人都可以提供一些建议吗?感谢你

4

4 回答 4

28

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

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

查看StrictRedis.__init__有一个参数decode_responses,默认情况下是False. https://github.com/andymccurdy/redis-py/blob/273a47e299a499ed0053b8b90966dc2124504983/redis/client.py#L446

传递decode_responses=True构造,对我来说,这解决了 OP 的问题。

于 2012-09-05T16:18:37.700 回答
7

更新,对于全局设置,检查jmoz 的答案

如果您使用的是第三方库,例如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 会自动对其进行编码以用于*set命令,通常为 UTF-8。对于*get命令,Redis 不知道值的形式类型,只需要str直接返回值。

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

此外,将默认编码设置为 UTF-8而不是使用ascii

于 2012-05-15T13:27:54.170 回答
6

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

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

In [8]: a.decode('utf8')
Out[8]: u'\u6bd4\u8d5b'
于 2012-05-15T10:54:00.330 回答
5

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

于 2012-05-15T12:09:44.473 回答