Conversión de excepción a una cadena en Python 3


¿Alguien tiene una idea, por qué este código Python 3.2

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

Funciona sin problemas (aparte de la codificación unicode en el shell de Windows :/), pero esto

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

Arrows TypeError: coercing to str: need bytes, bytearray or buffer-like object, Exception found ?

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

Editar

Tampoco funciona, 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 se puede convertir str () ¿una excepción interna a bytes?

Author: sorin, 2011-08-16

5 answers

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

Entonces, a menos que su excepción realmente devuelva una matriz de bytes codificada UTF-8 en su método personalizado __str__(), str(e, 'utf-8') no funcionará como se espera (intentaría interpretar una cadena de caracteres Unicode de 16 bits en RAM como una matriz de bytes codificada UTF-8 ...)

Mi conjetura es que su problema no es str() sino el print() (es decir, el paso que convierte la cadena Unicode de Python en algo que se vierte en su consola). Consulte esta respuesta para obtener soluciones: Python, Unicode y la consola de Windows

 38
Author: Aaron Digulla,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:00:31

Prueba esto, debería funcionar.

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

Considerando que solo tienes un mensaje en tu tupla interna.

 10
Author: Sebastiano Merlino,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-16 09:02:44

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

s = "Error {0}".format(str(e)) # string
utf8str = s.encode("utf-8") # byte array, representing utf8-encoded text
 4
Author: hamstergene,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-16 08:19:48

En Python 3, ya está en "espacio unicode" y no necesita codificación. Dependiendo de lo que quieras lograr, debes hacer la conversión inmediatamente antes de hacer las cosas.

Por ejemplo, puede convertir todo esto a bytes(), sino más bien en la dirección

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

.

 3
Author: glglgl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-16 08:44:18

Aquí hay una conversión independiente de la versión:

# 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)
 0
Author: tsionyx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-09 09:53:22