Jak uzyskać nazwę wyjątku, który został przechwycony w Pythonie?


122

Jak mogę uzyskać nazwę wyjątku, który został zgłoszony w Pythonie?

na przykład,

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

Na przykład łapię wiele (lub wszystkie) wyjątków i chcę wydrukować nazwę wyjątku w komunikacie o błędzie.


3
Jak myślisz, dlaczego tego potrzebujesz? Dlaczego except NameError:na początek nie złapać bardziej konkretnego wyjątku (np. )?

7
Mam kilka scenariuszy, w których chcę przechwycić wszystkie wyjątki (lub ich listę) i chcę wydrukować nazwę wyjątku w komunikacie o błędzie.
Rob Bednark

1
Możesz chcieć sprawdzić tracebackmoduł biblioteki standardowej , który ma funkcje, które wykonują ładne formatowanie wyjątków i śledzenia.
Blckknght

1
@delnan ta sytuacja pojawia się, gdy testujesz, czy funkcja
zgłasza

Potrzebowałem czegoś takiego, aby wysuszyć jakiś kod: wywoływana metoda może wywołać kilka wyjątków, każdy jest obsługiwany przez własną exceptinstrukcję, ale wpis dziennika jest bardzo podobny w każdym przypadku.
Adam Carroll,

Odpowiedzi:


224

Oto kilka różnych sposobów uzyskania nazwy klasy wyjątku:

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

na przykład,

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

6

To działa, ale wydaje się, że musi być prostszy, bardziej bezpośredni sposób?

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
Zastąp except Exception as exceptiontypem wyjątku, który chcesz złapać, tj except NameError as exception.
Maciej Gol

8
Nie chcę wychwytywać określonych z góry wyjątków. Chcę wyłapać wszystkie wyjątki.
Rob Bednark

3

Możesz także użyć sys.exc_info(). exc_info()zwraca 3 wartości: typ, wartość, śledzenie. Dokumentacja: 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

Jeśli chcesz w pełni kwalifikowaną nazwę klasy (np. sqlalchemy.exc.IntegrityErrorZamiast tylko IntegrityError), możesz użyć poniższej funkcji, którą zaczerpnąłem z niesamowitej odpowiedzi MB na inne pytanie (właśnie zmieniłem nazwy niektórych zmiennych, aby pasowały do ​​moich upodobań):

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__

Przykład:

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

Inne odpowiedzi tutaj są świetne do celów eksploracyjnych, ale jeśli głównym celem jest zarejestrowanie wyjątku (łącznie z nazwą wyjątku), być może rozważ użycie logging.exception zamiast drukowania?

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.