Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

Документы

Медиа

Назад
Вопрос про Python: Python, contextmanager, decorator, context manager, generator

Как работает декоратор contextmanager?

Вопрос проверяет понимание декоратора @contextmanager из модуля contextlib, который позволяет создавать контекстные менеджеры с помощью генераторов, упрощая управление ресурсами.

Короткий ответ

Декоратор @contextmanager из модуля contextlib позволяет превратить функцию-генератор в контекстный менеджер. Вместо написания класса с методами __enter__ и __exit__, вы пишете функцию с yield. Код до yield выполняется при входе в контекст (как __enter__), а код после — при выходе (как __exit__). Это упрощает создание менеджеров контекста для временных ресурсов, таких как файлы или соединения.

Длинный ответ

Декоратор @contextmanager — это инструмент стандартной библиотеки Python (модуль contextlib), который позволяет создавать контекстные менеджеры с использованием генераторов, избегая необходимости писать полноценный класс с методами __enter__ и __exit__. Контекстные менеджеры используются для управления ресурсами, гарантируя их корректное освобождение (например, закрытие файлов, откат транзакций).

Как это работает

Функция, декорированная @contextmanager, должна быть генератором и содержать ровно один yield. Код до yield выполняется при входе в блок with (аналог __enter__), а код после — при выходе из блока (аналог __exit__). Значение, возвращаемое yield, становится значением, присваиваемым переменной после as.

Пример использования

Рассмотрим создание контекстного менеджера для временного изменения текущей рабочей директории:

from contextlib import contextmanager
import os

@contextmanager
def temporary_cd(path):
    """Меняет директорию на время выполнения блока."""
    old_dir = os.getcwd()          # Код до yield — вход в контекст
    os.chdir(path)
    try:
        yield old_dir              # Значение, доступное в блоке 'as'
    finally:
        os.chdir(old_dir)          # Код после yield — выход из контекста

# Использование
with temporary_cd('/tmp') as prev_dir:
    print(f'Была директория: {prev_dir}')
    print(f'Сейчас в: {os.getcwd()}')
print(f'Вернулись в: {os.getcwd()}')

Где применяется

  • Управление ресурсами: автоматическое закрытие файлов, соединений с БД.
  • Временные изменения состояния: смена директории, модификация настроек.
  • Обеспечение транзакционности: откат изменений при ошибке.
  • Замер времени выполнения блока кода.

Важные аспекты

Код после yield выполняется всегда, даже если в блоке with возникло исключение. Для обработки исключений можно использовать try...except вокруг yield. Если исключение нужно подавить, можно использовать except и return True (как в __exit__).

Вывод: Декоратор @contextmanager стоит применять, когда нужно быстро создать простой контекстный менеджер без написания отдельного класса. Он идеален для сценариев, где управление ресурсом сводится к паре операций «установить/восстановить».

Уровень

  • Рейтинг:

    3

  • Сложность:

    4

Навыки

  • Python

    Python

Ключевые слова

#Python

#contextmanager

#decorator

#context manager

#generator

Подпишись на Python Developer в телеграм