Cuando estoy escribiendo sysadmin en Python, el búfer en sys.stdout que afecta a cada llamada a print() es molesto, porque yo don No quiero esperar a que se vacíe un buffer y luego obtener una gran cantidad de líneas a la vez en la pantalla, en cambio quiero obtener líneas de salida individuales tan pronto como el script genere un nuevo resultado. Ni siquiera quiero esperar nuevas líneas para ver la salida.La expresión idiomática estándar de Python para establecer el búfer sys.stdout en cero no funciona con Unicode
Un lenguaje utilizado a menudo para hacer esto en Python es
import os
import sys
sys.stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0)
Esto funcionó bien para mí durante mucho tiempo. Ahora me di cuenta de que no funciona con Unicode. Consulte el siguiente guión:
#!/usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import os
import sys
print('Original encoding: {}'.format(sys.stdout.encoding))
sys.stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0)
print('New encoding: {}'.format(sys.stdout.encoding))
text = b'Eisb\xe4r'
print(type(text))
print(text)
text = text.decode('latin-1')
print(type(text))
print(text)
Esto conduce al siguiente resultado:
Original encoding: UTF-8
New encoding: None
<type 'str'>
Eisb▒r
<type 'unicode'>
Traceback (most recent call last):
File "./export_debug.py", line 18, in <module>
print(text)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe4' in position 4: ordinal not in range(128)
Me tomó horas para rastrear la razón de ella (mi guión original era mucho más largo que este script mínima depuración) Es la línea
sys.stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0)
que utilicé durante años, así que no esperaba ningún problema con ella. Simplemente comente esta línea y la salida correcta debería verse así:
Original encoding: UTF-8
New encoding: UTF-8
<type 'str'>
Eisb▒r
<type 'unicode'>
Eisbär
Entonces, ¿qué es la secuencia de comandos para hacer? Para preparar mi código Python 2.7 lo más cerca posible a Python 3.x, siempre estoy usando
from __future__ import print_function, unicode_literals
que hace Python utilizan la nueva impresión() - función pero lo más importante: Realiza tienda de Python como todas las cadenas Unicode internamente de forma predeterminada. Tengo una gran cantidad de datos codificados/ISO-8859-1-1 Latina, por ejemplo
text = b'Eisb\xe4r'
para trabajar con él de la manera prevista, tengo que decodificarlo a Unicode en primer lugar, eso es lo que
text = text.decode('latin-1')
es para. Como la codificación predeterminada es UTF-8 en mi sistema, cada vez que imprimo una cadena, python codifica la cadena interna Unicode a UTF-8. Pero primero tiene que estar en perfecto Unicode internamente.
Ahora todo funciona bien en general, pero no con un buffer de salida de cero bytes hasta el momento. ¿Algunas ideas? Me di cuenta de que sys.stdout.encoding no está configurado después de la línea de almacenamiento en cero cero, pero no sé cómo configurarlo de nuevo. Es un atributo de solo lectura y las variables de entorno del sistema operativo LC_ALL o LC_CTYPE parecen evaluarse solo al comienzo del intérprete de Python.
Btw .: 'Eisbär' es la palabra alemana para 'oso polar'.
@martineau Bueno, la propuesta sys.stdout = codecs.getwriter ('utf8') (sys.stdout) tampoco funciona. Realmente probé y busqué mucho. Así que supongo que las ideas sin haberlas probado no ayudan mucho. –
He migrado la pregunta por usted. La próxima vez, simplemente "marca" la atención del moderador y dinos lo que necesitas. :) – slhck
@MartenLehmann: El hecho de que no fue probado es por qué lo publiqué como un comentario en lugar de una respuesta. – martineau