Як отримати назву винятку, що потрапив у Python?


122

Як я можу отримати ім'я виключення, яке було піднято в Python?

наприклад,

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

Наприклад, я вловлю декілька (або всі) винятку і хочу надрукувати ім'я виключення у повідомленні про помилку.


3
Чому ви вважаєте, що вам це потрібно? Чому б не except NameError:почати конкретніший виняток (наприклад ) для початку?

7
У мене є кілька сценаріїв, де я хочу знайти всі винятки (або їх список) і хочу надрукувати ім'я виключення у повідомленні про помилку.
Роб Беднарк

1
Можливо, ви хочете перевірити стандартний tracebackмодуль бібліотеки , який має функції, які виконують гарне форматування винятків та зворотних зворотів.
Blckknght

1
@delnan ця ситуація виникає, коли ви тестуєте, чи функція підвищує виняток, як запрограмовано
gokul_uf

Мені потрібно було щось подібне, щоб НАДУВИТИ якийсь код: кілька винятків можна збільшити методом, який я викликаю, кожен обробляється власним exceptтвердженням, але запис у журналі дуже схожий у кожному випадку.
Адам Керролл

Відповіді:


224

Ось кілька різних способів отримати назву класу винятку:

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

наприклад,

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

6

Це працює, але здається, що повинен бути простіший, прямий шлях?

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
Замініть except Exception as exceptionтипом винятку, який ви хочете зловити, тобто except NameError as exception.
Maciej Gol

8
Я не хочу ловити конкретні винятки, відомі заздалегідь. Я хочу зловити всі винятки.
Роб Беднарк

3

Ви також можете використовувати sys.exc_info(). exc_info()повертає 3 значення: тип, значення, трекбек. Про документацію: 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

Якщо ви хочете повністю кваліфікованого імені класу (наприклад, sqlalchemy.exc.IntegrityErrorзамість просто IntegrityError), ви можете скористатись функцією нижче, яку я взяв із дивовижної відповіді MB на інше питання (я просто перейменував деякі змінні, щоб задовольнити мій смак):

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__

Приклад:

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

Інші відповіді тут чудові для розвідки, але якщо першочерговою метою є реєстрація винятку (включаючи назву винятку), можливо, подумайте про використання logging.exception замість друку?

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.