¿Cómo obtener el nombre de la excepción que se detectó en Python?

122

¿Cómo puedo obtener el nombre de una excepción que se generó en Python?

p.ej,

try:
    foo = bar
except Exception as exception:
    name_of_exception = ???
    assert name_of_exception == 'NameError'
    print "Failed with exception [%s]" % name_of_exception

Por ejemplo, estoy detectando varias (o todas) excepciones y quiero imprimir el nombre de la excepción en un mensaje de error.

Rob Bednark
fuente
3
¿Por qué crees que necesitas esto? ¿Por qué no captar una excepción más concreta (por ejemplo except NameError:) para empezar?
7
Tengo un par de situaciones en las que quiero capturar todas las excepciones (o una lista de ellas) y quiero imprimir el nombre de la excepción en un mensaje de error.
Rob Bednark
1
Es posible que desee consultar el tracebackmódulo de la biblioteca estándar , que tiene funciones que realizan un buen formateo de excepciones y rastreos.
Blckknght
1
@delnan esta situación surge cuando está probando si una función
genera
Necesitaba algo como esto para SECAR algún código: el método al que estoy llamando pueden generar varias excepciones, cada una se maneja con su propia exceptdeclaración, pero la entrada de registro es muy similar en cada caso.
Adam Carroll

Respuestas:

224

Aquí hay algunas formas diferentes de obtener el nombre de la clase de la excepción:

  1. type(exception).__name__
  2. exception.__class__.__name__
  3. exception.__class__.__qualname__

p.ej,

try:
    foo = bar
except Exception as exception:
    assert type(exception).__name__ == 'NameError'
    assert exception.__class__.__name__ == 'NameError'
    assert exception.__class__.__qualname__ == 'NameError'
user1234
fuente
6

Esto funciona, pero parece que debe haber una forma más fácil y directa.

try:
    foo = bar
except Exception as exception:
    assert repr(exception) == '''NameError("name 'bar' is not defined",)'''
    name = repr(exception).split('(')[0]
    assert name == 'NameError'
Rob Bednark
fuente
4
Reemplácelo except Exception as exceptioncon el tipo de excepción que le gustaría detectar, es decir except NameError as exception.
Maciej Gol
8
No quiero detectar excepciones particulares conocidas de antemano. Quiero capturar todas las excepciones.
Rob Bednark
3

También puede utilizar sys.exc_info(). exc_info()devuelve 3 valores: tipo, valor, rastreo. Sobre la documentación: https://docs.python.org/3/library/sys.html#sys.exc_info

import sys

try:
    foo = bar
except Exception:
    exc_type, value, traceback = sys.exc_info()
    assert exc_type.__name__ == 'NameError'
    print "Failed with exception [%s]" % exc_type.__name__
moshfiqur
fuente
1

Si desea el nombre de clase completamente calificado (por ejemplo, en sqlalchemy.exc.IntegrityErrorlugar de solo IntegrityError), puede usar la función a continuación, que tomé de la increíble respuesta de MB a otra pregunta (acabo de cambiar el nombre de algunas variables para satisfacer mis gustos):

def get_full_class_name(obj):
    module = obj.__class__.__module__
    if module is None or module == str.__class__.__module__:
        return obj.__class__.__name__
    return module + '.' + obj.__class__.__name__

Ejemplo:

try:
    # <do something with sqlalchemy that angers the database>
except sqlalchemy.exc.SQLAlchemyError as e:
    print(get_full_class_name(e))

# sqlalchemy.exc.IntegrityError
MarredQueso
fuente
0

Las otras respuestas aquí son excelentes para fines de exploración, pero si el objetivo principal es registrar la excepción (incluido el nombre de la excepción), ¿quizás considere usar logging.exception en lugar de imprimir?

MrName
fuente