Cómo evitar el error de Python ' UnicodeEncodeError: ' ascii ' el códec no puede codificar caracteres … ' cuando se usa un script de Python en la línea de comando


Mejor respuesta

Lo sentimos, no existe una respuesta simple de una línea para este problema.

Imagine que una cadena entra en un programa de Python a través de una operación de E / S (leída desde la terminal, o desde un archivo, o desde la red), recorre el programa y se copia de un lugar a otro, y finalmente obtiene salida a través de una operación de E / S. En cualquier paso del camino, si asigna un Unicode a una cadena, «verá el temido ascii codec can"t encode... error. Desafortunadamente, no hay una manera fácil de solucionarlo aparte de ir a través de su código corrigiendo todos los puntos.

Por ejemplo, considere:

f\_in = open("filein.txt")

line = f\_in.read()

out\_msg = "The input line was: {line}".format(line=line)

f\_out = open("fileout.txt")

A menos que sepa qué codificación se usó al almacenar filein.txt, se encontrará con un comportamiento extraño y algunos caracteres en su line se verán como basura. (Nota: ganó » obtener el ascii codec can"t encode... error, pero los resultados serán malos de todos modos). Por lo tanto, debe usar algo como: f\_in = codecs.open("filein.txt", "rb", "utf-8") y luego esperar que quien haya almacenado filein.txt lo había almacenado en utf-8 y no en una de las otras codificaciones UTF. (Nota: utf-8 es compatible hacia arriba con ascii, por lo que un archivo que se almacenó usando ascii normal se abrirá bien usando la codificación utf-8).

A estas alturas, obviamente te habrás dado cuenta de que a menos que abra fileout.txt usando una codificación Unicode adecuada, nuevamente tendrá problemas y obtendrá el ascii codec can"t encode... error (si su out\_msg contiene algún carácter Unicode). Entonces debe hacer codecs.open("fileout.txt", "wb", "utf-8"). (Nota de nuevo: usar una codificación utf-8 para almacenar ascii normal no es un problema, ya que es compatible con versiones superiores, por lo que si su texto no contiene caracteres unicode que no sean ascii , el archivo codificado en utf-8 es idéntico a un archivo ascii normal.)

Lo que me hizo tropezar fue que hacer estas dos cosas no es lo suficientemente bueno. Considere este código actualizado:

f\_in = codecs.open("filein.txt", "rb", "utf-8")

line = f\_in.read()

out\_msg = "The input line was: {line}".format(line=line)

f\_out = codecs.open("fileout.txt", "wb", "utf-8")

Esto aún podría darle el mismo temido error en la tercera línea. Así es, el problema es que "The input line was: {line}".format(xxx)" es un str y si line contiene cualquier carácter Unicode (por lo que me refiero a caracteres que no se pueden codificar en ascii) está en problemas.

La solución para eso es:

out\_msg = u"The input line was: {line}".format(line=line)

(Sí, esta línea es diferente de la línea 3 en el ejemplo de código. Solo tiene que mirar con cuidado).

Así que ahí lo tiene. Necesita revisar cada línea de su código y encuentre lugares donde se asigna unicode a str (o se envía a un método que espera una str) y corrija el destino para que sea unicode en lugar de str.

Para entender unicode en Python mejor, eche un vistazo a: http://farmdev.com/thoughts/23/what-i-thought-i-knew-about-unicode-in-python-amounted-to-nothing/

Para entender Unicode en general (y yo altamente recomiendo que haga esto) lea Joel Spolsky «s» El mínimo absoluto que todo desarrollador de software debe conocer absoluta y positivamente sobre Unicode y conjuntos de caracteres (No Excuses!) «: http://www.joelonsoftware.com/articles/Unicode.html

Y mientras lo hace, también puede leer: ¿Cuál es la mejor fuente para aprender sobre las mejores prácticas de Unicode? en python?

Quick «n Dirty Hack: Si solo desea imprimir un resultado en ascii aproximado, puede hacer:

import unicodedata

line = unicodedata.normalize("NFKD", line).encode("ascii","ignore")

Esto reemplazará todos los caracteres no ascii con el equivalente ascii más cercano, o simplemente ignorará el carácter si nada es apropiado . Es lo suficientemente bueno para muchos propósitos …

Respuesta

Debe convertir sus cadenas Unicode (que están hechas de caracteres, una unidad desacoplada del tamaño de la memoria) en bytes usando la codificación adecuada antes de hacer cualquier E / S con él.

Por defecto, Python intenta codificar su cadena Unicode usando la codificación ASCII cuando escribe en stdout (es decir, usando print ), pero esta codificación «no puede representar todos los caracteres Unicode, por lo que aparece ese error»: el códec «ascii» no puede «codificar caracteres». Bastante explícito.

Debería elegir una codificación adecuada y codificar su cadena Unicode usando esa. Por ejemplo, UTF-8 es una codificación eficiente que puede manejar todos los caracteres Unicode. Suponiendo que foo es una cadena Unicode, podría (y debería) hacer: print foo.encode («utf -8 «) en lugar de solo print foo . Solo asegúrese de que su terminal o lo que sea que comprenda la codificación que elija.Nuevamente: UTF-8 es la codificación más popular que existe para escenarios como este, probablemente querrá usarla a menos que tenga necesidades muy específicas.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *