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.
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. –