Логотип YeaHub

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

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

Тренажёр

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

Обучение

Навыки

Войти

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

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

© 2026 YeaHub

Документы

Медиа

Назад
Вопрос про Python: Python, context manager, generator, contextlib, with statement

Как создать контекстный менеджер с помощью генератора?

Вопрос проверяет понимание создания контекстных менеджеров в Python с использованием генераторов и декоратора @contextlib.contextmanager, что необходимо для управления ресурсами и временем жизни объектов.

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

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

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

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

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

Декоратор @contextlib.contextmanager преобразует генераторную функцию в контекстный менеджер. Внутри функции:

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

Пример создания

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

import os
from contextlib import contextmanager

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

# Использование
with temporary_cd('/tmp'):
    print(os.getcwd())  # Выведет /tmp
print(os.getcwd())      # Вернётся к исходной директории

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

Такой подход удобен для:

  • Управления временными состояниями (например, изменение директории, перенаправление вывода).
  • Обеспечения чистки ресурсов (закрытие соединений, удаление временных файлов).
  • Создания лёгких контекстных менеджеров без написания отдельного класса.

Практический пример с обработкой исключений

Контекстный менеджер может обрабатывать исключения в блоке после yield. Например, менеджер для измерения времени выполнения:

import time
from contextlib import contextmanager

@contextmanager
def timer():
    start = time.time()
    try:
        yield
    finally:
        end = time.time()
        print(f'Execution time: {end - start:.2f} seconds')

with timer():
    time.sleep(1)  # Имитация долгой операции

Вывод: Execution time: 1.00 seconds. Код в finally гарантирует, что время будет выведено даже при возникновении исключения внутри блока.

Вывод

Создание контекстного менеджера через генератор с @contextlib.contextmanager — это лаконичный и читаемый способ для простых сценариев управления ресурсами. Используйте этот подход, когда не требуется сложная логика в методах __enter__/__exit__, чтобы избежать избыточного кода.

Уровень

  • Рейтинг:

    3

  • Сложность:

    4

Навыки

  • Python

    Python

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

#Python

#context manager

#generator

#contextlib

#with statement

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