Primero: reload(sys)
y establecer una codificación predeterminada aleatoria con respecto a la necesidad de un flujo de terminal de salida es una mala práctica.reload
a menudo cambia cosas en sys que se han implementado en función del entorno, por ejemplo, sys.stdin / stdout streams, sys.excepthook, etc.
Resolviendo el problema de codificación en stdout
La mejor solución que conozco para resolver el problema de codificación de print
las cadenas unicode y más allá de ascii str
(por ejemplo, de literales) en sys.stdout es: cuidar un sys.stdout (objeto similar a un archivo) que sea capaz y opcionalmente tolerante con respecto a las necesidades:
Cuando sys.stdout.encoding
sea None
por alguna razón, o no exista, o sea erróneamente falso o "menor" de lo que realmente es capaz el terminal o flujo stdout, intente proporcionar un .encoding
atributo correcto . Por fin reemplazándolo sys.stdout & sys.stderr
por un objeto similar a un archivo de traducción.
Cuando el terminal / flujo todavía no puede codificar todos los caracteres unicode que ocurren, y cuando no desea romperlos print
solo por eso, puede introducir un comportamiento de codificar con reemplazar en el objeto similar a un archivo de traducción.
Aquí un ejemplo:
#!/usr/bin/env python
# encoding: utf-8
import sys
class SmartStdout:
def __init__(self, encoding=None, org_stdout=None):
if org_stdout is None:
org_stdout = getattr(sys.stdout, 'org_stdout', sys.stdout)
self.org_stdout = org_stdout
self.encoding = encoding or \
getattr(org_stdout, 'encoding', None) or 'utf-8'
def write(self, s):
self.org_stdout.write(s.encode(self.encoding, 'backslashreplace'))
def __getattr__(self, name):
return getattr(self.org_stdout, name)
if __name__ == '__main__':
if sys.stdout.isatty():
sys.stdout = sys.stderr = SmartStdout()
us = u'aouäöüфżß²'
print us
sys.stdout.flush()
Uso de literales de cadena simple más allá de ascii en código Python 2/2 + 3
Creo que la única buena razón para cambiar la codificación predeterminada global (solo a UTF-8) se refiere a una decisión del código fuente de la aplicación , y no debido a problemas de codificación de flujo de E / S: para escribir literales de cadena más allá de ASCII en el código sin ser forzado usar siempre el u'string'
estilo de escape unicode. Esto se puede hacer de manera bastante consistente (a pesar de lo que dice el artículo de anonbadger ) cuidando una base de código fuente Python 2 o Python 2 + 3 que usa los literales de cadena simple ascii o UTF-8 de manera consistente, siempre que esas cadenas se sometan potencialmente en silencio conversión unicode y moverse entre módulos o potencialmente ir a stdout. Para eso, prefiere "# encoding: utf-8
"o ascii (sin declaración). Cambiar o descartar las bibliotecas que todavía dependen de una manera muy tonta fatalmente de los errores de codificación predeterminados de ascii más allá del chr # 127 (que es raro hoy en día).
Y haga esto al inicio de la aplicación (y / o a través de sitecustomize.py) además del SmartStdout
esquema anterior, sin usar reload(sys)
:
...
def set_defaultencoding_globally(encoding='utf-8'):
assert sys.getdefaultencoding() in ('ascii', 'mbcs', encoding)
import imp
_sys_org = imp.load_dynamic('_sys_org', 'sys')
_sys_org.setdefaultencoding(encoding)
if __name__ == '__main__':
sys.stdout = sys.stderr = SmartStdout()
set_defaultencoding_globally('utf-8')
s = 'aouäöüфżß²'
print s
De esta manera, los literales de cadena y la mayoría de las operaciones (excepto la iteración de caracteres) funcionan cómodamente sin pensar en la conversión unicode como si solo hubiera Python3. La E / S de archivos, por supuesto, siempre necesita un cuidado especial con respecto a las codificaciones, como sucede en Python3.
Nota: las cadenas simples se convierten implícitamente de utf-8 a unicode SmartStdout
antes de convertirse a la secuencia de salida encontrando.