Como obter o nome da exceção que foi capturada no Python?


122

Como posso obter o nome de uma exceção que foi gerada em Python?

por exemplo,

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

Por exemplo, estou capturando várias (ou todas) exceções e desejo imprimir o nome da exceção em uma mensagem de erro.


3
Por que você acha que precisa disso? Por que não pegar uma exceção mais concreta (por exemplo except NameError:) para começar?

7
Tenho alguns cenários em que desejo capturar todas as exceções (ou uma lista delas) e imprimir o nome da exceção em uma mensagem de erro.
Rob Bednark

1
Você pode querer verificar o tracebackmódulo da biblioteca padrão , que tem funções que fazem uma boa formatação de exceções e rastreamentos.
Blckknght

1
@delnan esta situação surge quando você está testando se uma função está gerando uma exceção conforme programado
gokul_uf

Eu precisava de algo assim para secar alguns códigos: várias exceções podem ser levantadas pelo método que estou chamando, cada uma é tratada com sua própria exceptinstrução, mas a entrada de log é muito semelhante em cada caso.
Adam Carroll,

Respostas:


223

Aqui estão algumas maneiras diferentes de obter o nome da classe da exceção:

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

por exemplo,

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

6

Isso funciona, mas parece que deve haver uma maneira mais fácil e direta?

try:
    foo = bar
except Exception as exception:
    assert repr(exception) == '''NameError("name 'bar' is not defined",)'''
    name = repr(exception).split('(')[0]
    assert name == 'NameError'

4
Substitua except Exception as exceptioncom o tipo de exceção que você gostaria de pegar, ou seja except NameError as exception.
Maciej Gol

8
Não quero capturar exceções particulares conhecidas com antecedência. Eu quero pegar todas as exceções.
Rob Bednark

3

Você também pode usar sys.exc_info(). exc_info()retorna 3 valores: tipo, valor, traceback. Na documentação: 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__

1

Se você quiser o nome de classe totalmente qualificado (por exemplo, em sqlalchemy.exc.IntegrityErrorvez de apenas IntegrityError), você pode usar a função abaixo, que tirei da resposta incrível de MB para outra pergunta (acabei de renomear algumas variáveis ​​para atender aos meus gostos):

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__

Exemplo:

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

# sqlalchemy.exc.IntegrityError

0

As outras respostas aqui são ótimas para fins de exploração, mas se o objetivo principal for registrar a exceção (incluindo o nome da exceção), talvez considere o uso de logging.exception em vez de print?

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.