2012-05-15 15 views
5

我使用的MongoDB和Redis的,Redis的是我的緩存。保存的Unicode中的Redis,但提取錯誤

我緩存MongoDB的對象與Redis的-PY:

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} 

與obj從hgetall 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)

任何人都可以提出一些建議嗎?感謝ü

+1

如何在redis中保存mongodb對象? – Denis

回答

7

更新,全局設置,檢查jmoz's answer

如果您在使用第三方的lib如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直接返回值。

因此,正如丹尼斯說,那你存儲對象Redis的方式是至關重要的。您需要將值轉換爲str以使Redis圖層透明。

此外,set the default encoding to UTF-8而是採用ascii

+0

他們爲什麼會自動編碼它,但只是給你一個字符串得到? – jmoz

+0

@jmoz我不確定,也許作者知道原因= p。但與psycopg2之類的適配器不同,通常redis-py客戶端不會存儲原始數據類型w /數據。因此,無法確切知道數據(字符串)的原始類型以及如何對其進行解碼。也許堅持'str'而不是接受其他類型的值,然後將它們隱式轉換爲'str'更好,但是誰知道。 – okm

+1

@okm我在前些日子發現了一些事情,請查看我的答案。 – jmoz

6

每串您可以使用decode功能UTF-8,例如其改造爲值,如果在代碼中標題字段:

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

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

人我想是喜是想使緩存不是解碼編碼的樂趣,但對增加他的系統。 – Denis

3

我建議你寫的MongoDB或Redis的(或任何外部系統)之前總是編碼成UTF-8。而且,當你對結果進行檢驗時,你會解碼('utf-8'),所以你總是在Python中使用Unicode。

25

我想我已經發現了這個問題。閱讀完這些之後,我不得不從redis明確解碼,這很痛苦,但是很有效。

我偶然發現一篇博客文章,其中作者的輸出是所有與我的obv不同的unicode字符串。

縱觀StrictRedis.__init__,有一個參數decode_responses默認爲Falsehttps://github.com/andymccurdy/redis-py/blob/273a47e299a499ed0053b8b90966dc2124504983/redis/client.py#L446

通過decode_responses=True在構建和我這個修復OP的問題。

+0

謝謝,我會稍後再試。這可能是最好的解決方案,因爲我不會搞亂我的代碼。 – goofansu

+0

這太棒了。謝謝。 –

+1

這應該是被接受的答案 – raben