0Pricing
Python Academy · Урок

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():
    pass

asynccontextmanager

В асинхронном коде используйте 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 — локальная установка не требуется.

Все уроки этого курса

  1. Оператор with подробно
  2. Протокол __enter__ и __exit__
  3. contextlib: @contextmanager
  4. Практические шаблоны менеджеров контекста
← Назад к Python Academy