Короткий ответ
Контекстный менеджер — объект, который гарантирует корректное освобождение ресурсов вроде файлов и соединений с помощью оператора with. Метод __enter__() выполняется при входе в блок, а __exit__() — при выходе, который происходит всегда, даже если возникло исключение.
Как это работает подробнее
Конструкция with избавляет от ручной очистки ресурсов и заменяет громоздкие связки try/finally.
- События входа и выхода. Код внутри
withвыполняется между__enter__()и__exit__(), а выход гарантирован и при нормальном завершении, и при ошибке. - Сигнатура __exit__(). Метод принимает тип исключения, значение и traceback; если ошибки не было, все три аргумента равны
None. - Классический пример.
open()возвращает контекстный менеджер: файл автоматически закрывается на выходе из блока, вызыватьclose()явно не нужно. - Цена утечки. Без закрытия ресурсов система может исчерпать файловые дескрипторы и соединения, замедлиться или упасть.
Пример кода
Собственный контекстный менеджер для файла
class FileManager:
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
def __enter__(self):
self.file = open(self.filename, self.mode)
return self.file
def __exit__(self, exc_type, exc_value, traceback):
self.file.close()
with FileManager('test.txt', 'w') as f:
f.write('Test')
print(f.closed) # True — файл закрыт автоматическиЧто использовать на практике
- Файлы и соединения. Работай с ними через
with, чтобы не оставлять дескрипторы открытыми. - Базы данных. Используй контекстные менеджеры для подключений и транзакций.
- Свои менеджеры. Выноси частую логику «открыть — гарантированно закрыть» в собственный класс.
Подводные камни
- Утечка ресурсов. Без
withфайлы и соединения могут не освободиться, особенно при исключениях. - Подавление ошибок. Если
__exit__()возвращает истину, исключение проглатывается, — по умолчанию возвращайNone. - Возврат из __enter__(). Именно возвращённое значение попадёт в переменную после
as, поэтому верни сам ресурс.
Как отвечать на собеседовании
- Дай определение контекстного менеджера и его назначение → назови методы
__enter__()и__exit__()→ приведи пример класса-менеджера для файла → подчеркни, что очистка выполняется даже при исключении, поэтому with заменяет try/finally.