¿Por qué recibo un error de encoding en python warnings.formatwarning en una cadena de formato?

Me sale un error de encoding en esta línea:

s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message) 

UnicodeEncodeError: el codec ‘ascii’ no puede codificar el carácter u ‘\ xc4’ en la posición 44: ordinal no está dentro del rango (128)

Intenté reproducir este error pasando todas las combinaciones de parámetros al formato de cadena, pero lo más cercano que obtuve fue el error “deencoding ascii” (al pasar unicode y una cadena ascii alta simultáneamente, lo que forzó la conversión de cadena a unicode, usando el decodificador ascii.

Sin embargo, no conseguí el error de “encoding ASCII”. ¿Alguien tiene una idea?

Esto sucede cuando Python intenta forzar un argumento:

 s = u"\u00fc" print str(s) UnicodeEncodeError: 'ascii' codec can't encode character u'\xfc' in position 0: ordinal not in range(128) 

Esto sucede porque uno de sus argumentos es un objeto (no una cadena de ningún tipo) y Python llama a str() en él. Hay dos soluciones: use una cadena Unicode para el formato ( s = u"%s..." ) o envuelva cada argumento con repr() .

Estás mezclando objetos unicode y str.

Explicación: En Python 2.x, hay dos tipos de objetos que pueden contener cadenas de texto. Str, y Unicode. str es una cadena de bytes, por lo que solo puede contener caracteres entre 0 y 255. Unicode es una cadena de caracteres Unicode.

Puede convertir entre str y unicode con los métodos “codificar” y “decodificar”:

 >>> "thisisastring".decode('ascii') u'thisisastring' >>> u"This is ä string".encode('utf8') 'This is \xc3\xa4 string' 

Tenga en cuenta las codificaciones. Las codificaciones son formas de representar texto Unicode como solo cadenas de bytes.

Si intenta agregar str y unicode juntos, Python intentará convertir uno a otro. Pero de forma predeterminada, utilizará ASCII como encoding, lo que significa az, AZ y algunos caracteres adicionales como !"#$%&/()=?'{[]]} Etc. Cualquier otra cosa fallará.

En ese punto, obtendrá un error de encoding o un error de deencoding, dependiendo de si Python intenta convertir el Unicode en str o str en Unicode. Por lo general, trata de decodificar, que se convierte a Unicode. Pero a veces decide no hacerlo sino coaccionar a cuerdas. No estoy completamente seguro de por qué.

Actualización: la razón por la que obtiene un error de encoding y no un error de desencoding es que el message en el código anterior no es ni str ni unicode. Es otro objeto, que tiene un método str . Python, por lo tanto, hace str (mensaje) antes de pasarlo, y eso falla, ya que el mensaje almacenado internamente es un objeto Unicode que no puede ser obligado a ascii.

O, simplemente responde: falla porque warnings.warn () no acepta mensajes Unicode.

Ahora, la solución:

No mezcle str y unicode. Si necesita usar Unicode, y aparentemente lo hace, intente asegurarse de que todas las cadenas estén unicode todo el tiempo. Esa es la única manera de estar seguro de evitar esto. Esto significa que cada vez que lea una cadena del disco o una llamada a una función que pueda devolver cualquier cosa que no sea pura ascii str, descodifíquela a Unicode lo antes posible. Y cuando necesite guardarlo en el disco o enviarlo a través de una red o pasarlo a un método que no comprenda Unicode, codifíquelo para que sea lo más tarde posible.

En este caso específico, el problema es que pasa Unicode a warnings.warn () y no puede hacer eso. Pasar una cadena Si no sabe qué es (como parece ser el caso aquí) porque proviene de algún otro lugar, sus soluciones try / except con una repr funcionan bien, aunque hacer una encoding sería una posibilidad.

Uno de los operandos que está pasando no es adecuado para la encoding ASCII, tal vez contenga caracteres Unicode o Latin-1. Cambie la cadena de formato a Unicode y vea qué sucede.