2009-11-30 20 views
23

estoy unPython: ¿Cómo hacer que StringIO.writelines acepte una cadena unicode?

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

en una cadena almacenada en 'a.desc' a continuación, ya que contiene el carácter '£'. Se almacena en el almacén de datos subyacente de Google App Engine como una cadena Unicode, así que está bien. La función cStringIO.StringIO.writelines está tratando de parecer tratando de codificar en formato ASCII:

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

¿Cómo se instruyen para el tratamiento de la codificación Unicode como si esa es la expresión correcta?

motor de aplicación se ejecuta en pitón 2,5

Respuesta

21

StringIO documentation:

A diferencia de los archivos de memoria implementadas por el módulo StringIO, los proporcionados por [cStringIO] no son capaces de aceptar cadenas Unicode que no puede ser codificado como cadenas simples ASCII.

Si es posible, use StringIO en lugar de cStringIO.

+1

Cambié (cStringIO está destinado a ser mejor en cuanto a rendimiento) y no arrojó un error, pero sí imprimió 'Â £' en lugar de solo '£'. ¿Por qué aparece 'Â' ahora? – rutherford

+4

'Â £' es la decodificación de Windows-1252 de 0xc2 0xa3 que es la codificación UTF-8 de u '£'. Tal vez su terminal, aplicación o donde sea que esté viendo eso está configurado para Windows-1252 en lugar de UTF-8. – Phil

+0

hmm. Básicamente estoy viendo una respuesta del servidor web a través del navegador Chrome. ¿Ese sería el problema? – rutherford

36

Puede envolver el objeto StringIO en un objeto codecs.StreamReaderWriter para codificar y decodificar automáticamente unicode.

De esta manera:

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 estará lleno de bytes codificación UTF-8.

Si entiendo su caso correctamente, sólo tendrá que escribir, por lo que también podría hacer:

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

Además, el objeto similar a un archivo devuelto por 'cStringIO.StringIO()' no funciona en la instrucción 'with', pero el contenedor devuelto por' codecs.StreamReaderWriter() 'sí lo hace. – steveha

+0

Esto suena similar a https://stackoverflow.com/q/45101658/562769 - ¿sabes la respuesta a mi pregunta? –

3

También puede codificar la cadena como UTF-8 de forma manual antes de añadir a la StringIO

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

use 'isinstance' en lugar de' type is X' – chown

0

Python 2.6 introdujo el módulo io y debería considerar usar io.StringIO(), "Una secuencia en memoria para texto Unicode".

En versiones antiguas de python esto no está optimizado (Python puro), en versiones posteriores esto se ha optimizado para el código C (rápido).

Cuestiones relacionadas