2011-11-04 15 views
9

Comenzaré diciendo que ya he visto esta publicación: Strange python print behavior with unicode, pero la solución ofrecida allí (usando PYTHONIOENCODING) no funcionó para mí.python Unicode manejando las diferencias entre print y sys.stdout.write

aquí está mi problema:

Python 2.6.5 (r265:79063, Apr 9 2010, 11:16:46) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2 
>>> a = u'\xa6' 
>>> print a 
¦ 

funciona bien, sin embargo:

>>> sys.stdout.write(a) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in ? 
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa6' in position 0: ordinal not in range(128) 

genera un error. La publicación a la que me he vinculado en la parte superior sugiere que esto se debe a que la codificación predeterminada de la consola es 'ascii'. Sin embargo, en mi caso no es:

>>> sys.stdout.encoding 
'UTF-8' 

¿Alguna idea de qué se está trabajando aquí y cómo solucionar este problema?

Gracias D.

+1

En pitón 2.7 con codificación de terminal utf-8, todo parece estar funcionando. ¿Puedes probar sys.stdout.write (a.encode ("UTF-8")) y tratar de ver qué pasa? – yasar

+0

Sí, funcionó ... Vaya, me acabo de dar cuenta de que utilicé una versión de Python incorrecta para generar la muestra. Debería haber usado 2.6.5. Entonces, ¿por qué está sucediendo esto? ¿Un error en pre 2.7 Python? –

+0

Aparentemente, al intentar escribir en stdout, Python intenta codificar su objeto unicode con ascii, pero falla miserablemente. No estoy seguro de por qué, pero el mío no lo hace :) – yasar

Respuesta

12

Esto es debido a un error de muchos años que era fixed en python-2.7, pero demasiado tarde para ser back-portado a python-2.6.

La documentación indica que cuando las cadenas de unicode se escriben en un archivo, se deben convertir a cadenas de bytes usando file.encoding. Pero esto no estaba siendo respetado por sys.stdout, que en cambio usaba la codificación Unicode predeterminada. Esto normalmente se establece en "ascii" por el módulo site, pero se puede cambiar con sys.setdefaultencoding:

Python 2.6.7 (r267:88850, Aug 14 2011, 12:32:40) [GCC 4.6.2] on linux3 
>>> a = u'\xa6\n' 
>>> sys.stdout.write(a) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
UnicodeEncodeError: 'ascii' codec cant encode character u'\xa6' ... 
>>> reload(sys).setdefaultencoding('utf8') 
>>> sys.stdout.write(a) 
¦ 

Sin embargo, una mejor solución podría consistir en sustituir sys.stdout con un envoltorio:

class StdOut(object): 
    def write(self, string): 
     if isinstance(string, unicode): 
      string = string.encode(sys.__stdout__.encoding) 
     sys.__stdout__.write(string) 

>>> sys.stdout = StdOut() 
>>> sys.stdout.write(a) 
¦ 
+0

stdout tiene muchas funciones diferentes (cerca, al ras, ...). Sería mejor aquí reemplazar la función de escritura solamente – halflings

Cuestiones relacionadas