Можно ли получить исключение из блока finally в Python?
Я использую конструкцию try
/finally
в своем скрипте. Возможно ли получить точное сообщение об ошибке внутри блока finally
?
3 ответ(ов)
Нет, в блоке finally
sys.exc_info
всегда будет значением None
, независимо от того, было ли исключение или нет. Используйте следующий паттерн:
try:
# код, который может вызвать исключение
whatever
except:
# здесь sys.exc_info возвращает информацию об исключении
# чтобы повторно вызвать исключение, используйте bare `raise`
raise
else:
# здесь вы можете быть уверены, что исключений не было
finally:
# здесь можно сделать завершающие действия, не зависящие от исключений
Таким образом, вы сможете корректно обрабатывать исключения и выполнять завершающие операции, не беспокоясь о состоянии sys.exc_info
в блоке finally
.
Блок finally
будет выполнен независимо от того, было ли выброшено исключение или нет, поэтому, как отмечает Джош, вы, скорее всего, не захотите обрабатывать исключение именно там.
Если вам действительно нужно получить значение исключения, которое было вызвано, то следует перехватить его в блоке except
, обработать его должным образом или повторно вывести, а затем использовать это значение в блоке finally
, при этом следует помнить, что оно может так и не установиться, если исключение в процессе выполнения не возникло.
import sys
exception_name = exception_value = None
try:
# выполнить действия
except Exception as e:
exception_name, exception_value, _ = sys.exc_info()
raise # или нет — решать вам
finally:
# что-то делать с exception_name и exception_value
# но помните, что они могут все еще быть None
Нет, в блоке finally
sys.exc_info
всегда будет возвращать все значения None
, независимо от того, произошло ли исключение или нет. Вместо этого используйте [это]:
Другой отвечающий прав в том, что вам следует обрабатывать это внутри блока except
.
Тем не менее, для сохранения информации и ради записи, вот ответ на исходный вопрос:
import sys
try:
int("not an integer LOL")
except:
e = sys.exc_info()[1]
# isinstance(e, ValueError) == True
raise # эта строка необязательна; я закомментировал её для примера вывода
else:
e = None # вы должны сделать это, чтобы избежать NameError
finally:
print("Мне действительно хотелось получить доступ к %s внутри блока finally. И я делаю это сейчас."
% repr(e))
Это выведет что-то вроде:
Мне действительно хотелось получить доступ к
ValueError("invalid literal for int() with base 10: 'not an integer LOL'")
внутри блока finally. И я делаю это сейчас.
Как напечатать исключение в Python?
Как изменить порядок столбцов в DataFrame?
'pip' не распознан как командa внутреннего или внешнего формата
Почему statistics.mean() работает так медленно?
Есть ли разница между поднятием экземпляра класса Exception и самого класса Exception?