2011-08-16 16 views
35

¿Alguien tiene una idea, ¿por qué este 3.2 de código Pythonconversión de Excepción a una cadena en Python 3

try:  
    raise Exception('X') 
except Exception as e: 
    print("Error {0}".format(str(e))) 

obras sin problema (aparte de la codificación Unicode en Windows Shell: /), pero esto

try:  
    raise Exception('X') 
except Exception as e: 
    print("Error {0}".format(str(e, encoding = 'utf-8'))) 

throws TypeError: coercing a str: necesita bytes, bytearray o un objeto tipo buffer, Excepción encontrada?

Cómo convertir un error en una cadena con codificación personalizada?

Editar

No funciona bien, si hay \ u2019 en el mensaje:

try:  
    raise Exception(msg) 
except Exception as e: 
    b = bytes(str(e), encoding = 'utf-8') 
    print("Error {0}".format(str(b, encoding = 'utf-8'))) 

Pero ¿por qué no puede STR() convertir una excepción a nivel interno bytes?

+2

¿Usted intentó 'str (e) .encode ('UTF-8')'? – agf

+1

@agf Sí devuelve bytes en lugar de cadena.Puedo usarlo como reemplazo de bytes (str (e), encoding = 'utf-8'), pero siempre tengo que hacer la segunda conversión bytes => str –

+0

"why can not str() convert to bytes" - cómo sería saber a qué codificación convertir? Además, su nuevo código es equivalente a .format (str (e)) – hamstergene

Respuesta

31

En Python 3.x, str(e) debería poder convertir cualquier Exception en una cadena, incluso si contiene caracteres Unicode.

Así que a menos que su excepción realidad devuelve una matriz de bytes UTF-8 codificado en su método personalizado __str__(), str(e, 'utf-8') no funcionará como se espera (que sería tratar de interpretar una cadena de caracteres de 16 bits Unicode en la memoria RAM como una matriz de bytes UTF-8 codificado ...)

Supongo que su problema no es str() sino el print() (es decir, el paso que convierte la cadena de Unicode de Python en algo que se descarga en la consola). Consulte esta respuesta para encontrar soluciones: Python, Unicode, and the Windows console

+0

de hecho, al principio tuve un problema con * UnicodeEncodeError: el códec 'charmap' no puede codificar el carácter ... * en shell bajo la versión francesa de Win 7. Parecía más portátil convertir explícitamente todo a utf-8, en lugar de usar algunos envoltorios personalizados dependientes del os. –

4

En Python3, string no tiene tal atributo como la codificación. Siempre es unicode internamente. Para las cadenas codificadas, existen matrices de bytes:

s = "Error {0}".format(str(e)) # string 
utf8str = s.encode("utf-8") # byte array, representing utf8-encoded text 
+0

No según la especificación: http://docs.python.org/py3k/library/functions.html#str –

+0

Es solo un parámetro para el constructor, que hace que descodifique la matriz de bytes para unicode asumiendo esta codificación. – hamstergene

+0

Entonces no entiendo tu respuesta. ¿Podrías elaborarlo un poco? –

7

Pruebe esto, debería funcionar.

try:  
    raise Exception('X') 
except Exception as e: 
    print("Error {0}".format(str(e.args[0])).encode("utf-8")) 

Teniendo en cuenta que sólo tiene un mensaje en su tupla interna.

+0

Fue lo primero que intenté, por desgracia: * AttributeError: el objeto 'Exception' no tiene atributo 'message' * –

+0

Oh, tienes razón; es porque en la versión> 3 Python usa argumentos y no mensajes. –

+0

prueba esta nueva versión –

3

En Python 3, ya se encuentra en el "espacio Unicode" y no necesita codificación. Dependiendo de lo que quiere lograr, debe hacer la conversión inmediatamente antes de hacer las cosas.

E.g. usted puede convertir todo esto a bytes(), sino más bien en la dirección

bytes("Error {0}".format(str(e)), encoding='utf-8') 

.

0

Hay una conversión de la versión agnóstica aquí:

# from the `six` library 
import sys 
PY2 = sys.version_info[0] == 2 
if PY2: 
    text_type = unicode 
    binary_type = str 
else: 
    text_type = str 
    binary_type = bytes 

def exc2str(e): 
    if e.args and isinstance(e.args[0], binary_type): 
     return e.args[0].decode('utf-8') 
    return text_type(e) 

y pruebas para ello:

def test_exc2str(): 
    a = u"\u0856" 
    try: 
     raise ValueError(a) 
    except ValueError as e: 
     assert exc2str(e) == a 
     assert isinstance(exc2str(e), text_type) 
    try: 
     raise ValueError(a.encode('utf-8')) 
    except ValueError as e: 
     assert exc2str(e) == a 
     assert isinstance(exc2str(e), text_type) 
    try: 
     raise ValueError() 
    except ValueError as e: 
     assert exc2str(e) == '' 
     assert isinstance(exc2str(e), text_type) 
Cuestiones relacionadas