from contextlib import ContextDecorator class mycontext(ContextDecorator): # код контекстного менеджера
Базовый класс ContextDecorator()
модуля contextlib
который позволяет использовать менеджер контекста в качестве декоратора.
Менеджеры контекста, унаследованные от класса contextlib.ContextDecorator()
, должны реализовывать методы __enter__
и __exit__
как обычно. Метод __exit__
сохраняет необязательную обработку исключений даже при использовании в качестве декоратора.
Класс contextlib.ContextDecorator
используется функцией contextlib.contextmanager()
, поэтому вы получаете эту функцию автоматически.
ContextDecorator
:from contextlib import ContextDecorator class mycontext(ContextDecorator): def __enter__(self): print('Starting') return self def __exit__(self, *exc): print('Finishing') return False >>> @mycontext() ... def function(): ... print('The bit in the middle') ... >>> function() # Starting # The bit in the middle # Finishing >>> with mycontext(): ... print('The bit in the middle') ... # Starting # The bit in the middle # Finishing
Это изменение является просто синтаксическим сахаром для любой конструкции следующей формы:
def f(): with contextmanager(): # какой то код
Вместо этого класс ContextDecorator
позволяет написать:
@contextmanager() def f(): # какой то код
Последний пример кода дает понять, что contextmanager
относится ко всей функции, а не просто к ее части, а так же уменьшается уровень отступа.
Существующие менеджеры контекста, которые уже имеют базовый класс, могут быть расширены с помощью contextlib.ContextDecorator()
в качестве смешанного класса:
from contextlib import ContextBaseClass, ContextDecorator class mycontext(ContextBaseClass, ContextDecorator): def __enter__(self): return self def __exit__(self, *exc): return False
Примечание.
Поскольку декорированная функция должна вызываться несколько раз, базовый менеджер контекста должен поддерживать использование нескольких операторов with
. Если это не так, то следует использовать исходную конструкцию с явным оператором with
внутри функции.