MiddleКодЧастоЕщё не отвечали
Напишите контекстный менеджер для очистки ресурса
Реализуйте контекстный менеджер, который захватывает ресурс, отдаёт его в блок with и всегда освобождает.
Требования:
- Печатать "acquire" при входе и "release" при выходе.
- Освобождение должно срабатывать, даже если тело бросает исключение.
from contextlib import contextmanager
@contextmanager
def open_resource(name):
# ваш код здесь
with open_resource("db") as r:
print(f"using {r}")
Допишите реализацию.
Используйте @contextlib.contextmanager: захватите до yield value (привязывается к as), а освобождение — в finally, чтобы очистка шла даже при исключении. Это эквивалент класса с __enter__ / __exit__. with гарантирует выполнение кода после yield.
- ✗Опускать
try/finally, из-за чего очистка пропускается при исключении тела - ✗Использовать
returnвместоyieldв@contextmanager - ✗Освобождать до
yield, из-за чего тело выполняется после очистки
- →Как
@contextmanagerсопоставляет код до/послеyieldс__enter__/__exit__? - →Что может
__exit__, чего блокуfinallyв@contextmanagerсделать непросто?
Оглавление
Задача
Реализуйте контекстный менеджер через @contextmanager, который захватывает ресурс, отдаёт его в блок и всегда освобождает.
Решение
from contextlib import contextmanager
@contextmanager
def open_resource(name):
print(f"acquire {name}")
try:
yield name # значение, привязываемое к 'as'
finally:
print(f"release {name}") # выполняется даже при исключении
with open_resource("db") as r:
print(f"using {r}")
Ключевые моменты
- Код до
yield— это__enter__; код вfinallyпослеyield— это__exit__. try/finallyгарантирует освобождение даже при исключении внутри блокаwith.yield(неreturn) отдаёт ресурс и приостанавливает генератор до выхода из блока.
Оглавление