contextlib: @contextmanager
Лаконично создавайте менеджеры контекста с помощью декоратора contextlib.
«contextlib: @contextmanager» — бесплатный урок Python Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Python Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Python Academy содержит 4 уроков всего.
Зачем нужен contextlib?
contextlib.contextmanager позволяет записать менеджер контекста в виде функции-генератора, а не класса, и сократить объём шаблонного кода.
from contextlib import contextmanager
@contextmanager
def managed():
print("setup")
yield
print("teardown")
with managed():
print("inside")Возврат значения
Всё, что Вы передаёте через yield, присваивается переменной as в операторе with.
from contextlib import contextmanager
@contextmanager
def temp_list():
lst = []
yield lst
print(f"Final list: {lst}")
with temp_list() as lst:
lst.append(1)
lst.append(2)Обработка исключений в @contextmanager
Оберните yield в try/finally, чтобы гарантировать очистку даже при возникновении исключения.
from contextlib import contextmanager
@contextmanager
def safe_open(path):
f = open(path)
try:
yield f
finally:
f.close()
with safe_open("data.txt") as f:
print(f.read())Подавление исключений
Перехватите исключение внутри генератора, чтобы подавить его, — это эквивалентно возврату True из __exit__.
from contextlib import contextmanager
@contextmanager
def ignore_value_errors():
try:
yield
except ValueError:
pass
with ignore_value_errors():
raise ValueError("ignored")contextlib.suppress
contextlib.suppress(*exceptions) — готовый менеджер контекста, который подавляет исключения указанных типов.
from contextlib import suppress
with suppress(FileNotFoundError):
open("missing.txt")
print("continues")contextlib.closing
closing(obj) создаёт менеджер контекста, вызывающий obj.close() при выходе. Это полезно для объектов, у которых есть close(), но нет __exit__.
from contextlib import closing
from urllib.request import urlopen
with closing(urlopen("https://example.com")) as page:
content = page.read()contextlib.nullcontext
nullcontext — пустой менеджер контекста, не выполняющий никаких действий. Он полезен, когда менеджер контекста является необязательным.
from contextlib import nullcontext
def process(data, lock=None):
cm = lock if lock is not None else nullcontext()
with cm:
return [x*2 for x in data]contextlib.ExitStack
ExitStack позволяет динамически управлять переменным количеством менеджеров контекста.
from contextlib import ExitStack
files = ["a.txt", "b.txt", "c.txt"]
with ExitStack() as stack:
handles = [stack.enter_context(open(f)) for f in files]
data = [h.read() for h in handles]Повторное использование @contextmanager
Менеджер контекста на основе генератора можно использовать только один раз при каждом вызове. Чтобы использовать его снова, повторно вызовите декорированную функцию.
from contextlib import contextmanager
@contextmanager
def counter():
count = 0
yield lambda: count.__add__ # each call is independent
print("done")
with counter():
pass
with counter():
passasynccontextmanager
В асинхронном коде используйте contextlib.asynccontextmanager, чтобы записывать менеджеры async with в виде генераторов.
from contextlib import asynccontextmanager
@asynccontextmanager
async def async_session():
session = await create_session()
try:
yield session
finally:
await session.close()contextlib.redirect_stdout
Временно перенаправляйте стандартный вывод в любой объект, подобный файлу.
import io
from contextlib import redirect_stdout
buf = io.StringIO()
with redirect_stdout(buf):
print("captured")
print(buf.getvalue()) # capturedБыстрая проверка
Где следует разместить код очистки в генераторе @contextmanager, чтобы гарантировать его выполнение даже при исключении?
Итоги
@contextmanager превращает генератор в менеджер контекста. Используйте try/finally вокруг yield для безопасной очистки. Модуль contextlib также предоставляет suppress, nullcontext, ExitStack и другие средства.
Часто задаваемые вопросы
Урок «contextlib: @contextmanager» бесплатный?
Да — полный текст урока «contextlib: @contextmanager» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Python Academy, подпишись на CoddyKit PRO. Курс Python Academy содержит 4 уроков всего.
Чему я научусь в уроке «contextlib: @contextmanager»?
Лаконично создавайте менеджеры контекста с помощью декоратора contextlib. Ты практикуешь Python Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Python Academy?
Предыдущий опыт не требуется. Python Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «contextlib: @contextmanager»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Python Academy?
Да. Каждый урок Python Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Оператор with подробно
- Протокол __enter__ и __exit__
- contextlib: @contextmanager
- Практические шаблоны менеджеров контекста