Короткий ответ
Внутри блока except для повторного возбуждения того же исключения используют raise без аргументов: сначала выполняют свои действия, например логирование, затем передают ошибку дальше. Такой raise сохраняет исходный traceback и работает только в обработчике.
Как это работает подробнее
Приём полезен, когда на одном уровне нужно залогировать ошибку или дополнить контекст, а окончательное решение об обработке принимает внешний код.
- Голый raise. Повторно возбуждает именно текущее исключение, поэтому работает только внутри блока
except. - Сохранение traceback. В отличие от
raiseс новым исключением, исходная цепочка вызовов сохраняется целиком. - Ошибка вне except. Использовать голый
raiseвне обработчика нельзя: возбуждать текущее исключение нечего, и интерпретатор выдаст ошибку. - Сцепление исключений. Для замены одного исключения другим с указанием причины пишут
raise новое_исключение from старое_исключение.
Пример кода
Логирование с повторным возбуждением
try:
1 / 0
except ZeroDivisionError:
print('Записываем ошибку в лог...')
raise # повторно возбуждаем то же исключение
# Программа завершится с ZeroDivisionError и полным tracebackЧто использовать на практике
- Логирование. Записывай ошибку в обработчике и пробрасывай её голым
raise, не теряя стек вызовов. - Обёртки. Если нужен другой тип ошибки, используй
raise ... from ..., чтобы сохранить причину. - Единый уровень. Оставляй финальное решение о реакции на ошибку внешнему коду.