Развернутое объяснение
Контекстный менеджер — это объект, который умеет настраивать некоторый контекст перед выполнением блока кода и гарантированно его «убирать» после, независимо от того, завершился блок успешно или с исключением. Конструкция with как раз и используется для работы с такими объектами:
with open("data.txt") as f:
contents = f.read()
# здесь файл уже закрытВ этом примере при входе в блок with у объекта файла вызывается __enter__, возвращаемое значение попадает в переменную f;
при выходе (даже если read() бросит исключение) будет вызван __exit__, который закроет файл. with — это «синтаксический сахар» над типичной конструкцией try/finally, упрощающий правильную работу с ресурсами.
Как это выглядит внутри? Любой объект можно сделать контекстным менеджером, реализовав два метода:
class MyContext:
def __enter__(self):
# код при входе в контекст (настройка ресурса)
return self # то, что попадёт в переменную после as
def __exit__(self, exc_type, exc_val, exc_tb):
# код при выходе (освобождение ресурса, логирование и т.п.)
# вернуть True, чтобы «поглотить» исключение, или False/None, чтобы пробросить
...Использование:
with MyContext() as ctx:
# код внутри контекста
...На собеседовании обычно достаточно сказать, что контекстный менеджер — это объект с методами __enter__ и __exit__, а with гарантирует вызов __exit__ при выходе из блока.
Практические примеры использования with
Типичные сценарии использования контекстного менеджера, о которых полезно упомянуть:
Работа с файлами:
with open("log.txt", "a") as log_file:
log_file.write("New event\n")
# файл закрыт автоматическиБлокировки и потоки:
from threading import Lock
lock = Lock()
with lock:
# критическая секция
...Временное изменение окружения, таймеры и т.п.
import time
class Timer:
def __enter__(self):
self.start = time.time()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.end = time.time()
print(f"Elapsed: {self.end - self.start:.3f}s")
with Timer():
do_something()Такие примеры часто спрашивают на интервью, чтобы проверить, понимаете ли вы идею «автоматической уборки».