Иногда желательно перехватывать исключения из реализации метода __enter__
, без непреднамеренного перехвата исключений из тела оператора with
или метода __exit__
менеджера контекста.
Чтобы сделать это, используя класс contextlib.ExitStack()
, шаги в протоколе управления контекстом могут быть слегка разделены:
stack = ExitStack() try: x = stack.enter_context(cm) except Exception: # обрабатываем исключение `__enter__` else: with stack: # Нормальное использование
Фактически необходимость в этом указывает на то, что базовый API должен обеспечивать прямой интерфейс управления ресурсами для использования с операторами try
/except
/finally
, но не все API хорошо разработаны в этом отношении.
Когда контекстный менеджер является единственным предоставляемым API управления ресурсами, тогда класс contextlib.ExitStack()
может упростить обработку различных ситуаций, которые не могут быть обработаны непосредственно в операторе with
.