Поведение __cause__ и __context__ в исключениях Python

Поведение __cause__ и __context__ в исключениях Python

@python_quiz

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

Коротко: код вручную связывает два атрибута исключения с одним объектом-исключением. В результате выводит имя типа исходного исключения и True для проверки идентичности ссылки.

Условие (код)

python

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

  • Создаем класс DataError, наследник Exception.
  • Создаем объект e типа ValueError с сообщением 'raw'.
  • Создаем объект d типа DataError с сообщением 'wrapped'.
  • Явно присваиваем d.__cause__ = e и d.__context__ = e — оба атрибута теперь ссылаются на один и тот же объект e.
  • В выражении print берём type(d.__cause__).__name__ — это имя класса объекта, на который ссылается __cause__ (то есть "ValueError").
  • Сравниваем d.__cause__ is d.__context__ — это проверка по идентичности объектов; так как обе ссылки указывают на один объект e, результат будет True.

Итоговый вывод программы:

Демонстрация (запустите в Python)

python

Ожидаемый вывод:

Анализ вариантов ответов

  • "Выведет: ValueError -> True" — соответствует поведению кода: тип объекта, на который указывает __cause__, — ValueError, и обе переменные ссылаются на один объект, так что is вернёт True.
  • "Выведет: ValueError -> False" — неверно, потому что здесь __cause__ и __context__ явно назначены на один и тот же объект.
  • "Выведет: DataError -> False" — неверно: тип __cause__ — не DataError, а ValueError, и у нас не разные объекты.
  • "Будет поднято необработанное исключение" — неверно: в коде исключение не поднимается после создания; мы просто вручную присваиваем атрибуты — никаких необработанных исключений не возникает.

Небольшие замечания о __cause__ и __context__

  • Атрибуты __cause__ и __context__ — обычные ссылки на объекты исключений; их можно присваивать вручную (как в примере) или они могут устанавливаться интерпретатором при цепочке исключений.
  • Оператор "raise ... from ..." используется для явного задания причины — это влияет на отображение цепочки при печати трассировки, но в данном квизе мы работаем с явным присваиванием.
  • Проверка is сравнивает идентичность объектов (т.е. указывает ли ссылка на тот же объект), а не только эквивалентность по значениям.

Вывод

Код печатает имя типа исходного исключения и True, потому что оба атрибута __cause__ и __context__ указывают на один и тот же объект ValueError. Это простой пример, который показывает разницу между типом исключения, ссылками на объекты и тем, как Python хранит информацию о цепочке исключений.

Report Page