Как получить имя исключения, которое было обнаружено в 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оператором, но запись в журнале очень похожа в каждом случае.
Адам Кэрролл,

Ответы:

226

Вот несколько разных способов получить имя класса исключения:

  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'
user1234
источник
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
Я не хочу ловить заранее известные конкретные исключения. Я хочу поймать все исключения.
Роб Беднарк
4

Вы также можете использовать 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__
moshfiqur
источник
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
MarredCheese
источник
1

Другие ответы здесь отлично подходят для исследовательских целей, но если основная цель - зарегистрировать исключение (включая имя исключения), возможно, рассмотрите возможность использования logging.exception вместо print?

MrName
источник