2009-09-24 9 views
16

Supongamos por un momento que no se puede usar print (y así disfrutar del beneficio de la detección automática de codificación). Entonces eso nos deja con sys.stdout. Sin embargo, sys.stdout es tan tonto como not do any sensible encoding.Escribir cadenas unicode a través de sys.stdout en Python

Ahora se lee la página wiki Python PrintFails y se va a probar el siguiente código:

$ python -c 'import sys, codecs, locale; print str(sys.stdout.encoding); \ 
    sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout); 

Sin embargo esto también no funciona (al menos en Mac). Demasiado ver por qué:

>>> import locale 
>>> locale.getpreferredencoding() 
'mac-roman' 
>>> sys.stdout.encoding 
'UTF-8' 

(UTF-8 es lo que entiende el terminal).

Así se cambia el código anterior para:

$ python -c 'import sys, codecs, locale; print str(sys.stdout.encoding); \ 
    sys.stdout = codecs.getwriter(sys.stdout.encoding)(sys.stdout); 

Y ahora cadenas Unicode se envían correctamente a sys.stdout y por lo tanto impresos correctamente en el terminal (sys.stdout está unido al terminal).

¿Es esta la forma correcta de escribir cadenas de Unicode en sys.stdout o debería estar haciendo otra cosa?

EDITAR: a veces - por ejemplo, cuando la tubería de la salida a less - sys.stdout.encoding será None. en este caso, el código anterior fallará.

+0

s/my/la de uno/para la coherencia – icedwater

Respuesta

3

No es claro para mí por qué no podría imprimir; pero suponiendo que sí, el enfoque me parece correcto.

+1

Una de las razones por las que no puedo usar 'print' es para evitar ese espacio extra de impresiones 'print'. Mire el uso de 'sys.stdout' aquí: http://stackoverflow.com/questions/1396820/apt-like-column-output-python-library/1397382#1397382 –

+3

Puede construir líneas completas, y luego imprimir ellos. –

+0

¡Bravo! Sí, en ese caso puedo usar 'print' –

10

La mejor idea es comprobar si está conectado directamente a un terminal. Si es así, use la codificación del terminal. De lo contrario, use la codificación preferida del sistema.

if sys.stdout.isatty(): 
    default_encoding = sys.stdout.encoding 
else: 
    default_encoding = locale.getpreferredencoding() 

También es muy importante permitir siempre que el usuario especifique la codificación que desee. Normalmente lo hago una opción de línea de comandos (como -e ENCODING) y lo analizo con el módulo optparse.

Otra cosa buena es no sobrescribe sys.stdout con un codificador automático. Crea tu codificador y úsalo, pero deja sys.stdout solo. Puede importar bibliotecas de terceros que escriben cadenas de bytes codificadas directamente al sys.stdout.

8

Hay una variable de entorno opcional "PYTHONIOENCODING" que se puede configurar con la codificación predeterminada deseada. Sería una forma de capturar la codificación deseada por el usuario de una manera consistente con todo Python. Está enterrado en el manual de Python here.

27
export PYTHONIOENCODING=utf-8 

hará el trabajo, pero no puede configurarlo en python en sí ...

lo que podemos hacer es verificar si no se pone y pedir al usuario que lo puso delante de la escritura llamada con:

if __name__ == '__main__': 
    if (sys.stdout.encoding is None): 
     print >> sys.stderr, "please set python env PYTHONIOENCODING=UTF-8, example: export PYTHONIOENCODING=UTF-8, when write to stdout." 
     exit(1) 
+0

Muchas gracias, funciona para mí. – Kino

6

Esto es lo que estoy haciendo en mi solicitud:

sys.stdout.write(s.encode('utf-8'))

Este es el punto de referencia exactamente lo contrario para la lectura de los nombres UTF-8 de argv:

for file in sys.argv[1:]: 
    file = file.decode('utf-8') 

Esto es muy feo (en mi humilde opinión) ya que te obliga a trabajar con UTF-8 .. que es la norma en Linux/Mac, pero no en Windows ... Funciona para mí de todos modos :)

Cuestiones relacionadas