El siguiente código funciona bien con Python3 en mi máquina con Windows e imprime el carácter ‘é’:
data = b"\xc3\xa9" print(data.decode('utf-8'))
Sin embargo, ejecutar el mismo en un contenedor docker basado en Ubuntu da como resultado:
UnicodeEncodeError: 'ascii' codec can't encode character '\xe9' in position 0: ordinal not in range(128)
¿Hay algo que deba instalar para habilitar la deencoding de utf-8?
El problema es con la expresión print()
, no con el método decode()
. Si observa detenidamente, la excepción que se genera es un Unicode En codeError, no un – De codeError.
Cada vez que utiliza la función print()
, Python convierte sus argumentos en una str
y posteriormente codifica el resultado en bytes
, que se envían al terminal (o lo que sea que se ejecute en Python). El códec que se utiliza para la encoding (por ejemplo, UTF-8 o ASCII) depende del entorno. En un caso ideal,
En su caso, la segunda condición no se cumple para la ventana acoplable de Linux que menciona: la encoding utilizada es ASCII, que solo admite caracteres encontrados en una máquina de escribir inglesa antigua. Estas son algunas opciones para abordar este problema:
LC_ALL
en algo que contiene “UTF-8” funcionó para mí una vez. Tendrá que ponerlos en el script de inicio para el shell que ejecuta su terminal, por ejemplo. .bashrc . Vuelva a codificar STDOUT, así:
sys.stdout = open(sys.stdout.buffer.fileno(), 'w', encoding='utf8')
La encoding utilizada debe coincidir con la del terminal.
sys.stdout
, por ejemplo. sys.stdout.buffer.write("é".encode('utf8'))
. Esto es, por supuesto, mucho más repetitivo que print("é")
. De nuevo, la encoding utilizada debe coincidir con la del terminal. print()
completo. Use open(fn, encoding=...)
para la salida, el módulo de registro para la información de progreso, dependiendo de qué tan interactivo sea su script, esto podría valer la pena (es cierto que probablemente enfrentará el mismo problema de encoding al escribir en STDERR con el módulo de registro). Puede haber otras opciones, pero dudo que haya mejores.
Parece que Ubuntu, según la versión, utiliza una encoding u otra como predeterminada, y puede variar entre shell y python también. Adoptado de esta publicación y también de este blog :
Por lo tanto, la forma recomendada parece ser decirle a tu instancia de Python que use utf-8
como encoding predeterminada:
Establezca su encoding predeterminada de los archivos fuente de Python a través de la variable de entorno:
export PYTHONIOENCODING=utf8
Además, en los archivos de origen puede indicar la encoding que prefiere usar explícitamente, por lo que debería funcionar independientemente de la configuración del entorno (consulte esta pregunta + respuesta , documentos de Python y PEP 263 :
#!/usr/bin/env python3 # -*- coding: utf-8 -*- ....
Con respecto a la interpretación de la encoding de los archivos leídos por python, puede especificarlo explícitamente en el comando de abrir
with open(fname, "rt", encoding="utf-8") as f: ...
y hay una forma más intrincada con algunos efectos secundarios, pero te permite especificarlo explícitamente cada vez
import sys # sys.setdefaultencoding() does not exist, here! reload(sys) # Reload does the trick! sys.setdefaultencoding('UTF8')
Lea las advertencias sobre este truco en la respuesta y los comentarios relacionados .