2009-11-30 14 views
23

Sto diventando unPython: come ottenere StringIO.writelines per accettare una stringa unicode?

UnicodeEncodeError: 'ascii' codec can't encode character u'\xa3' in position 34: ordinal not in range(128) 

su una stringa memorizzata in 'a.desc' seguito in quanto contiene il carattere '£'. È archiviato nell'archivio dati di Google App Engine sottostante sotto forma di stringa unicode, quindi va bene. La funzione cStringIO.StringIO.writelines sta cercando apparentemente cercando di codificare in formato ASCII:

result.writelines(['blahblah',a.desc,'blahblahblah']) 

Come faccio istruzioni al fine di trattare la codifica unicode come se questo è il fraseggio corretto?

App Engine gira su Python 2.5

risposta

21

StringIO documentation:

A differenza dei file di memoria attuate dal modulo StringIO, quelli forniti da [cStringIO] non sono in grado di accettare stringhe Unicode che non possono essere codificati come semplici stringhe ASCII.

Se possibile, utilizzare StringIO anziché cStringIO.

+1

Sono passato (cStringIO è destinato a migliorare le prestazioni) e non ha generato un errore, ma ha stampato "£" invece di "£". Perché ora viene visualizzato? – rutherford

+4

'£' è la decodifica Windows-1252 di 0xc2 0xa3 che è la codifica UTF-8 di u '£'. Forse il tuo terminale, app o ovunque tu stia vedendo che è configurato per Windows-1252 anziché UTF-8. – Phil

+0

hmm. Essenzialmente sto guardando una risposta del server web attraverso il browser Chrome. Questo sarebbe il problema? – rutherford

36

È possibile avvolgere l'oggetto StringIO in un oggetto codecs.StreamReaderWriter per codificare e decodificare automaticamente unicode.

Così:

import cStringIO, codecs 
buffer = cStringIO.StringIO() 
codecinfo = codecs.lookup("utf8") 
wrapper = codecs.StreamReaderWriter(buffer, 
     codecinfo.streamreader, codecinfo.streamwriter) 

wrapper.writelines([u"list of", u"unicode strings"]) 

buffer sarà riempito con byte UTF-8 codificato.

Se ho ben capito il tuo caso in modo corretto, si avrà solo bisogno di scrivere, così si potrebbe anche fare:

import cStringIO, codecs 
buffer = cStringIO.StringIO() 
wrapper = codecs.getwriter("utf8")(buffer) 
+1

Inoltre, l'oggetto simile a file restituito da 'cStringIO.StringIO()' non funziona nell'istruzione 'with', ma il wrapper restituito da' codecs.StreamReaderWriter() 'sì! – steveha

+0

Sembra simile a https://stackoverflow.com/q/45101658/562769 - conosci la risposta alla mia domanda? –

3

È anche possibile codificare la stringa come UTF-8 manualmente prima di aggiungerlo alla StringIO

for val in rows: 
    if isinstance(val, unicode): 
     val = val.encode('utf-8') 
result.writelines(rows) 
+2

usa 'isinstance' invece di' type è X' – chown

0

Python 2.6 ha introdotto il modulo io e si dovrebbe considerare l'utilizzo di io.StringIO(), "Un flusso in memoria per testo Unicode".

Nelle versioni python precedenti questo non è ottimizzato (puro Python), nelle versioni successive questo è stato ottimizzato per il codice C (veloce).

Problemi correlati