Ответ
Да, постоянно использую контекстные менеджеры в Python. Это один из ключевых паттернов языка для управления ресурсами (файлы, сетевые соединения, транзакции БД), гарантирующий их корректное освобождение, даже если в блоке кода произошло исключение.
Стандартное использование с файлами и сетевыми ресурсами:
# Автоматическое закрытие файла
with open('data.json', 'r') as f:
data = json.load(f)
# Файл закрыт здесь, даже если внутри блока было исключение
# Работа с сессиями requests
with requests.Session() as session:
session.auth = ('user', 'pass')
response = session.get('https://api.example.com/data')
# Сессия корректно закрыта
Создание собственного контекстного менеджера с помощью класса:
import sqlite3
from contextlib import contextmanager
class DatabaseConnection:
def __init__(self, db_path):
self.db_path = db_path
self.conn = None
def __enter__(self):
self.conn = sqlite3.connect(self.db_path)
self.conn.execute('PRAGMA foreign_keys = ON') # Пример настройки
return self.conn
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is None:
self.conn.commit() # Коммит, если не было ошибок
else:
self.conn.rollback() # Откат при ошибке
self.conn.close()
# Использование
with DatabaseConnection('app.db') as conn:
cursor = conn.cursor()
cursor.execute('INSERT INTO users (name) VALUES (?)', ('Alice',))
# Соединение гарантированно закрыто, транзакция завершена
Использование декоратора @contextmanager из contextlib:
from contextlib import contextmanager
import time
@contextmanager
def timer(operation_name):
"""Контекстный менеджер для замера времени выполнения."""
start = time.perf_counter()
try:
yield
finally:
end = time.perf_counter()
print(f"{operation_name} took {end - start:.4f} seconds")
with timer("Data processing"):
# Долгая операция
process_large_dataset()
В реальных проектах я применял контекстные менеджеры для управления пулами соединений с БД, временной смены текущей директории (contextlib.chdir), а также для реализации механизма блокировок (lock) при работе с многопоточным кодом.