Исключения и chaining: как работает raise ... from ... в Python

Исключения и chaining: как работает raise ... from ... в Python

@python_quiz

Разберем этот квиз

Коротко: код показывает создание пользовательского исключения с привязкой к исходному через конструкцию raise ... from .... Разберём, что печатает программа и почему.

Код квиза

python

Что делает raise ... from ...

  • Конструкция raise NewException(...) from OriginalException(...) явно связывает исключение NewException с причинным исключением OriginalException.
  • При этом у нового исключения устанавливается атрибут __cause__, который ссылается на объект исходного исключения.
  • Если from не используется, но исключение происходит во время обработки другого — Python может заполнить __context__, а __cause__ останется None, если явно не задан.
  • Форматирование трассировки и строки зависит от этих атрибутов, но мы в коде читаем именно type(e).__name__ и type(e.__cause__).__name__.

Разбор вывода

В блоке except Exception as e: переменная e содержит поднятое исключение — это экземпляр ConfigError. Выражения в print:

  • type(e).__name__ — имя класса текущего исключения, то есть "ConfigError".
  • type(e.__cause__).__name__ — имя класса причинного исключения, установленного через from, то есть "FileNotFoundError".

Поэтому строка, которая будет напечатана:

Анализ предложенных вариантов

  • Вариант с ConfigError -> FileNotFoundError совпадает с реальным выводом — т.к. __cause__ явно задан через from.
  • ConfigError -> None мог бы появиться, если бы from не использовался и __cause__ оставался пустым (и при этом __context__ не выводился в печати), но в нашем коде from есть.
  • FileNotFoundError -> ConfigError неверен: текущим исключением является ConfigError, а не FileNotFoundError.
  • Exception -> FileNotFoundError неверен, потому что type(e).__name__ возвращает конкретный класс исключения (ConfigError), а не базовый Exception.

Дополнительные замечания

  • Атрибуты исключений:

- __cause__ — явно заданная причина через from.
- __context__ — автоматически сохраняет предыдущее исключение, если оно случилось во время обработки другого.
- __suppress_context__ — если установлено в True, подавляет показ __context__ в трассировке при наличии __cause__.

  • Для отладки полезно смотреть полную трассировку (traceback), но для задач с доступом к объектам исключений чтение __cause__ даёт точный ответ на связь исключений.

Вывод

Код демонстрирует явную цепочку исключений: новое исключение оборачивает исходное с помощью from, поэтому печатается имя текущего исключения и имя причинного исключения — "ConfigError -> FileNotFoundError".

Report Page