2012-05-15 9 views
5

Sto usando mongodb e redis, redis è la mia cache.Salva unicode in redis ma recupero errore

sto caching degli oggetti mongodb con 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} 

l'obj prelevato dalla Redis con hgetall (chiave, 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'} 

Come si può vedere, obj inverosimile dalla cache è str invece di unicode, quindi nella mia app ci sono errori come: il codec 'ascii' non può decodificare il byte 0xe6 in posizione 12: ordinale non nel range (128)

Qualcuno può dare qualche suggerimento? grazie

+1

E come si salvano gli oggetti mongodb in redis? – Denis

risposta

7

Aggiornamento, per l'impostazione globale, verificare jmoz's answer.

Se si sta utilizzando di terze parti come ad esempio lib django-redis, potrebbe essere necessario specificare una personalizzata ConnectionFactory:

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

Supponendo che si sta utilizzando Redis-py, è meglio per passare str anziché unicode a Redis, oppure Redis will encode it automatically per i comandi *set, normalmente in UTF-8. Per i comandi *get, Redis non ha idea del tipo formale di un valore e deve semplicemente restituire direttamente il valore in str.

Quindi, come ha detto Denis, il modo in cui si memorizza l'oggetto su Redis è fondamentale. È necessario trasformare il valore in str per rendere il livello Redis trasparente per te.

Inoltre, set the default encoding to UTF-8 invece di utilizzare ascii

+0

Perché dovrebbero codificarlo automaticamente ma poi ti lasciano una stringa? – jmoz

+0

@jmoz Non sono sicuro, forse l'autore conosce il motivo = p.Ma a differenza dell'adattatore come psycopg2, normalmente il client redis-py non memorizza il datatype originale con i dati. Quindi non c'è modo di sapere esattamente quale tipo di dati (stringa) è originariamente e come decodificarlo. Forse insistere su 'str' invece di accettare altri tipi di valore, quindi convertirli in' str' implicitamente, è meglio, ma chi lo sa. – okm

+1

@okmono Ho trovato qualcosa l'altro giorno riguardo a questo, controlla la mia risposta. – jmoz

6

per ogni stringa è possibile utilizzare la funzione decode per trasformarla in utf-8, ad es. per il valore se il campo titolo nel codice:

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

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

Man Penso che ciao sia fare la cache non per decodificare la codifica, ma per aumentare il suo sistema. – Denis

3

vi consiglio codificare sempre UTF-8 prima di scrivere a MongoDB o Redis (o qualsiasi sistema esterno). E che decodificate ('utf-8') quando selezionate i risultati, in modo da lavorare sempre con Unicode in Python.

25

penso di aver scoperto il problema. Dopo aver letto questo, ho dovuto decodificare esplicitamente da redis che è un dolore, ma funziona.

Mi sono imbattuto in un post sul blog in cui l'output dell'autore era costituito da stringhe Unicode che erano completamente diverse dalle mie.

Guardando nello StrictRedis.__init__ c'è un parametro decode_responses che di default è False. https://github.com/andymccurdy/redis-py/blob/273a47e299a499ed0053b8b90966dc2124504983/redis/client.py#L446

Passare in decode_responses=True sul costrutto e per me questo FISSA IL PROBLEMA DELL'OP.

+0

Grazie, proverò più tardi. Questa forse è la soluzione migliore in quanto non rovinerò il mio codice. – goofansu

+0

Questo è fantastico. Grazie. –

+1

Questa dovrebbe essere la risposta accettata – raben

Problemi correlati