Как работает raise ... from и атрибут __cause__ в Python

Как работает raise ... from и атрибут __cause__ в Python

@python_quiz

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

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

Исходный код

python

Если запустить этот код, он выведет:

Пошаговый разбор

  1. Определяем собственный класс исключения ParseError, унаследованный от Exception.
  2. В блоке try выполняется raise ParseError('parsed') from ValueError('raw').

- Это создаёт новое исключение ParseError с сообщением 'parsed'.
- Ключевое — from ValueError('raw') явно связывает исходное исключение ValueError('raw') как причину текущего.
- Внутреннее св-во ParseError.__cause__ будет указывать на объект ValueError('raw').

  1. В блоке except ParseError as e мы ловим возникший ParseError и обращаемся к e.__cause__.

- type(e.__cause__).__name__ даёт имя класса причины: ValueError.
- e.__cause__.args[0] — первое (и в данном случае единственное) аргумент-сообщение: 'raw'.

Почему остальные варианты неверны (кратко)

  • Нельзя получить ParseError parsed — это бы означало, что мы печатаем имя типа текущего исключения и его сообщение. В примере печатаются имя типа причины и её сообщение.
  • None raw не подходит, потому что __cause__ не None: он установлен через from. (Если бы использовали from None, тогда __cause__ стал бы None.)
  • ValueError parsed неверно, потому что сообщение, связанное с причиной, — 'raw', а не 'parsed'.

Дополнения: __cause__ vs __context__ и suppress

  • __cause__ — устанавливается явно через raise NewExc from OldExc.
  • __context__ — Python автоматически сохраняет предыдущее исключение в __context__, если новое возбуждается в обработчике, но не использовалась конструкция from.
  • from None — подавляет автоматическую цепочку и приводит к тому, что __cause__ будет None, а __context__ при показе трассировки может быть скрыт.

Примеры для сравнения:

python
python

Вывод

Использование raise ... from ... явно связывает новое исключение с причиной, сохраняя исходное исключение в атрибуте __cause__. В рассматриваемом примере это даёт вывод имени типа причины ValueError и её сообщения raw. Такая явная цепочка полезна для понятных трассировок ошибок и передачи контекста при обработке исключений.

Report Page