Контекстные менеджеры и протокол `with`
Python
Senior
Яндекс
Как работает протокол контекстного менеджера в Python? Покажите, как реализовать собственный контекстный менеджер без `contextlib` и с помощью декоратора `contextmanager`.
Ответы
Контекстные менеджеры
Контекстный менеджер реализует методы `__enter__` и `__exit__`. Конструкция `with` гарантирует вызов `__exit__` даже при исключении.
Классический вариант:
```python
class Timer:
def __enter__(self):
import time
self.start = time.perf_counter()
return self
def __exit__(self, exc_type, exc, tb):
import time
self.elapsed = time.perf_counter() - self.start
with Timer() as t:
...
print(t.elapsed)
```
Через `contextlib.contextmanager`:
```python
from contextlib import contextmanager
import time
@contextmanager
def timer():
start = time.perf_counter()
try:
yield
finally:
print('elapsed', time.perf_counter() - start)
```