Контекстный менеджер Python: подавление выбранных типов исключений

Напишите решение на Python и проверьте его на странице.

Другие упражнения по этой теме: Контекстные менеджеры Python: задачи на with, откат и исключения.

Фильтр семейств исключений

Программа управления числовым фрезерным станком следит за ходом обработки детали и сообщает о любых отклонениях программными исключениями Python. Некоторые сбои возникают из-за естественной шероховатости заготовки и считаются допустимыми, тогда как перегрев привода или заклинивание шпинделя требуют немедленной аварийной остановки.

Чтобы отделить штатные заминки от критических неполадок, выполнение блока команд оборачивают в менеджер контекста, настроенный на кортеж разрешённых классов исключений. Если тип возникшей ошибки совпадает с одним из них или наследуется от него, менеджер подавляет исключение и сохраняет перехваченный объект в своём атрибуте для последующего анализа. Любые другие исключения, не входящие в разрешённые ветки иерархии типов, должны беспрепятственно проходить наружу.

Реализуйте класс менеджера контекста, который выборочно гасит ошибки по иерархии классов и фиксирует сам экземпляр подавленного сбоя.

Что уже дано

В редакторе объявлен класс ExceptionFamilyFilter с сигнатурами методов __init__, __enter__ и __exit__, содержащими заглушки raise NotImplementedError.

В среде исполнения уже доступны вспомогательные классы и функции для тестирования менеджера (иерархия исключений ProcessFault, генераторы проверок и транзакционные пробы), реализовывать их заново не требуется.

Что нужно сделать

Реализуйте класс ExceptionFamilyFilter(allowed_types: tuple[type[BaseException], ...]).

Правила работы менеджера:

  • Конструктор принимает кортеж allowed_types, содержащий от 0 до 16 реальных классов исключений Python (наследников BaseException).
  • При инициализации атрибут caught экземпляра устанавливается в None.
  • Метод __enter__() активирует контекст и возвращает сам объект менеджера (self).
  • При нормальном выходе из блока with (без исключений) атрибут caught остаётся равным None, а метод __exit__ не выполняет подавления.
  • Если внутри блока with возникает исключение, класс которого совпадает с любым из переданных в allowed_types или является его подклассом (с учётом множественного наследования), менеджер:
  • сохраняет точный экземпляр возникшего исключения в атрибут self.caught;
  • подавляет ошибку, возвращая истинное значение из __exit__.
  • Если кортеж allowed_types пуст, ни одно исключение не подавляется.
  • Любые исключения, не подпадающие под разрешённые типы, не должны подавляться или подменяться: метод __exit__ возвращает ложное значение (False или None), ошибка беспрепятственно всплывает дальше, а self.caught остаётся None.

Ввод и вывод

Стандартные потоки ввода stdin и вывода stdout не используются: считывать ввод и вызывать print() в решении не требуется. Проверяющая система после выполнения скрипта получает класс верхнего уровня ExceptionFamilyFilter и тестирует его работу в блоках with.

Пример использования

error = ValueError("rough")
manager = ExceptionFamilyFilter((Exception,))
with manager as entered:
    raise error
print(entered is manager)
print(manager.caught is error)

Вывод:

True
True
РешениеPython

Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.

Отправьте решение, чтобы увидеть результаты тестов.

Связанные задачи