我正在使用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'编解码器无法解码位置12中的字节0xe6:序数不在范围内(128)
有人能提出一些建议吗?谢谢你
答案 0 :(得分:26)
我想我发现了这个问题。读完之后,我不得不从redis中明确解码,这很痛苦,但是很有效。
我偶然发现了一篇博客文章,其中作者的输出是所有unicode字符串,与我的不同。
查看StrictRedis.__init__
时,参数decode_responses
默认为False
。 https://github.com/andymccurdy/redis-py/blob/273a47e299a499ed0053b8b90966dc2124504983/redis/client.py#L446
在构造上传递decode_responses=True
,对我来说,这可以修复OP问题。
答案 1 :(得分:7)
更新,对于全局设置,请检查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
命令,通常{ {3}}。对于*get
命令,Redis不知道值的正式类型,只需直接返回str
中的值。
因此,正如Denis所说,将对象存储到Redis的方式至关重要。您需要将值转换为str
以使Redis图层对您透明。
另外,in UTF-8而非使用ascii
答案 2 :(得分:6)
对于每个字符串,您可以使用decode
函数在utf-8中对其进行转换,例如:对于代码中的标题字段的值:
In [7]: a='\xe6\xaf\x94\xe8\xb5\x9b'
In [8]: a.decode('utf8')
Out[8]: u'\u6bd4\u8d5b'
答案 3 :(得分:4)
我建议您在写入MongoDB或Redis(或任何外部系统)之前始终编码为utf-8。并且你在结果时解码('utf-8'),这样你就可以在Python中使用Unicode。