2009-10-06 15 views
5

me sale error codificación en esta línea:¿Por qué obtengo un error de codificación en python warnings.formatwarning en la cadena de formato?

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

UnicodeEncodeError: códec 'ascii' no puede codificar caracteres u '\ XC4' en la posición 44: No ordinales en el rango (128)

traté para reproducir este error pasando todas las combinaciones de parámetros al formato de cadena, pero lo más cerca que conseguí fue "ascii decode" error (pasando unicode y cadena ascii alta simultáneamente, lo que forzó la conversión de cadena a unicode, usando el decodificador ascii.

Sin embargo, no logré obtener el error de "cifrado ASCII". ¿Alguien tiene una idea?

+1

Oh, lo obtienes cuando se llama warnings.warn ... ¿No podrías haberlo dicho? No estaba claro si el código no era su código, sino la biblioteca estándar. Debería decir cuál es su problema, no una pregunta genérica que crea que es el problema, porque generalmente no lo es. He actualizado mi respuesta a continuación con más detalles. –

Respuesta

8

Esto sucede cuando Python intenta coaccionar a 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 se debe a que uno de sus argumentos es un objeto (no una cadena de cualquier tipo) y Python llama str() en él. Hay dos soluciones: use una cadena Unicode para el formato (s = u"%s...") o envuelva cada argumento con repr().

+1

El formato está en el módulo de advertencias, por lo que prefiero no cambiarlo, pero agregar repr() alrededor de los parámetros pasados ​​suena realmente bien. ¡Gracias! –

+0

Luego obtendrá presupuestos extra y un extra u. Funciona como un truco, pero no es muy bonito. –

+1

Se produce un error cuando se captura la advertencia lanzada por la base de datos para un registro. Como el registro falló, estoy totalmente en la oscuridad sobre el problema original, que es el peor lugar para estar. Me gustan mis registros legibles como la siguiente persona, así que decidí ajustar el formato en una prueba: excepto: bloquear, hacerlo primero "muy bien" y usar repr() solo en el caso de un error de codificación, incluyendo lanzar una advertencia adicional sobre el problema de codificación. En mi humilde opinión, eso no es un truco, es mejor, más seguro, la tala. –

1

Uno de los operandos que está pasando no es adecuado para la codificación ASCII; quizás contenga caracteres Unicode o Latin-1. Cambie la cadena de formato a Unicode y vea qué sucede.

+0

Esto debería producir un _decode_ error, es decir s = "% s% s"% (unichr (2000), chr (200)) El error aquí parece ser otra cosa. –

+0

@cortex: A veces, Python decide no forzar a unicode, sino que coacciona a la cadena. No estoy seguro de cómo se toma esa decisión. –

8

Está 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.

Usted puede convertir entre str y unicode con los métodos "decodificar" "codificar" y:

>>> "thisisastring".decode('ascii') 
u'thisisastring' 

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

Nota las codificaciones. Las codificaciones son formas de representar texto unicode como cadenas de bytes.

Si intentas agregar str y unicode juntos, Python intentará convertir uno a otro. Pero por defecto usará ASCII como codificación, lo que significa a-z, A-Z, y algunos caracteres adicionales como !"#$%&/()=?'{[]]}, etc. Cualquier otra cosa fallará.

En ese momento, obtendrá un error de codificación o un error de decodificación, dependiendo de si Python intenta convertir el Unicode a str o str a unicode. Por lo general, trata de decodificar, es decir, convertir a Unicode. Pero a veces decide no hacerlo, pero forzar a la cadena. No estoy del todo seguro de por qué.

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

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

Ahora, la solución:

No mezcle str y Unicode. Si necesita utilizar Unicode, y aparentemente lo hace, intente asegurarse de que todas las cadenas sean unicode todo el tiempo. Esa es la única forma de estar seguro de evitar esto. Esto significa que cada vez que lee una cadena del disco o una llamada a una función que puede devolver algo más que ascii str puro, decodifíquelo a unicode lo antes posible. Y cuando necesite guardarlo en un disco o enviarlo a través de una red o pasarlo a un método que no entienda unicode, codifíquelo a str lo más tarde posible.

En este caso específico, el problema es que pasas unicode a warnings.warn() y no puedes hacer eso. Pasa una cuerda. Si no sabes qué es (como parece ser el caso aquí) porque viene de otro lado, tus soluciones try/except con una repr funcionan bien, aunque hacer una codificación sería una posibilidad para.

+2

Creo que el interlocutor es perfectamente consciente del hecho de que el unicode y str están mezclados de alguna manera; la pregunta es por qué este error se desencadena en una operación que normalmente debería forzar la salida a unicode. –

+1

Posible, pero fui a una respuesta exhaustiva. Y el problema sigue siendo la mezcla de Unicode y Str. Por qué se produce un error en lugar del otro en este caso específico, no lo sé, no puedo reproducirlo. Pero lo he visto suceder yo mismo. –

+1

Así es como puedes reproducirlo: 'advertencias de importación; warnings.warn (u'Предупреждение ') ' –

Cuestiones relacionadas