← Назад к вопросам

Приведи пример использования контекстного менеджера

2.3 Middle🔥 161 комментариев
#Python Core#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Контекстные менеджеры в Python

Контекстный менеджер — это объект, который определяет, что происходит при входе в блок with и при выходе из него. Это очень полезный инструмент для управления ресурсами (файлы, подключения, блокировки и т.д.).

Базовый пример: работа с файлами

# Без контекстного менеджера (плохо)
f = open("data.txt", "r")
data = f.read()
f.close()  # может не выполниться, если будет ошибка

# С контекстным менеджером (хорошо)
with open("data.txt", "r") as f:
    data = f.read()
# файл автоматически закроется, даже если будет исключение

В этом примере объект f — контекстный менеджер, который гарантирует закрытие файла в любом случае.

Создание собственного контекстного менеджера

Твой класс должен реализовать методы __enter__ и __exit__:

class DatabaseConnection:
    def __init__(self, db_url):
        self.db_url = db_url
        self.connection = None
    
    def __enter__(self):
        print(f"Подключаюсь к базе: {self.db_url}")
        self.connection = self._create_connection()
        return self.connection  # это значение присваивается переменной после as
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("Закрываю соединение")
        if self.connection:
            self.connection.close()
        # возвращаем False, чтобы исключения распространялись дальше
        return False
    
    def _create_connection(self):
        # здесь логика подключения
        return "connection_object"

# Использование
with DatabaseConnection("postgresql://localhost") as conn:
    print(f"Работаю с: {conn}")
    # даже если здесь будет ошибка, __exit__ выполнится

Использование декоратора contextmanager

Есть более простой способ с модулем contextlib:

from contextlib import contextmanager

@contextmanager
def database_connection(db_url):
    print(f"Подключаюсь к: {db_url}")
    conn = f"connection_{db_url}"  # имитация подключения
    try:
        yield conn  # отдаём ресурс в блок with
    finally:
        print(f"Закрываю: {conn}")  # гарантированно выполнится

# Использование
with database_connection("postgres://localhost") as conn:
    print(f"Использую: {conn}")

Практический пример: работа с файлами и логированием

from contextlib import contextmanager
import logging

@contextmanager
def logged_operation(operation_name):
    logger = logging.getLogger(__name__)
    logger.info(f"Начинаю: {operation_name}")
    
    try:
        yield
    except Exception as e:
        logger.error(f"Ошибка в {operation_name}: {e}")
        raise
    finally:
        logger.info(f"Завершил: {operation_name}")

# Использование
with logged_operation("Импорт данных"):
    # твой код здесь
    data = [1, 2, 3]
    print(f"Обработано: {len(data)} элементов")

Пример с несколькими ресурсами

# Python 3.10+ позволяет использовать несколько менеджеров
with open("input.txt") as input_file, open("output.txt", "w") as output_file:
    for line in input_file:
        output_file.write(line.upper())
# оба файла закроются автоматически

Почему контекстные менеджеры важны

  1. Безопасность ресурсов — гарантируют очистку даже при исключениях
  2. Читаемость — код понятнее и структурнее
  3. Избежание утечек — файлы, подключения, блокировки всегда закрываются
  4. Меньше кода — не нужно помнить о finally блоках

Контекстные менеджеры — это один из принципов правильного управления ресурсами в Python.