Короткий ответ
Контекстный менеджер — объект с методами __enter__ и __exit__, гарантирующий выполнение кода освобождения ресурса (например, закрытие файла) даже если внутри блока произошло исключение.
Как это работает подробнее
При входе в блок with Python вызывает __enter__() объекта и присваивает результат переменной после as; при выходе из блока (нормальном или через исключение) гарантированно вызывается __exit__(), которому передаются тип, значение и traceback исключения, если оно было.
Пример кода
example-247.py
with open("data.txt", "w") as f:
f.write("hello")
raise ValueError("что-то пошло не так")
# файл всё равно будет закрыт корректно - это видно, если сохранить ссылку на f
# вне блока и проверить f.closed == True после выходаЧто использовать на практике
- Практика.
open()возвращает файловый объект, который сам является контекстным менеджером — его__exit__вызываетclose(). Это избавляет от необходимости вручную писатьtry/finallyдля закрытия файла, лока или соединения.
Подводные камни
- Риски. Открывают файл без
withи забывают закрыть его явно, особенно в ветке с исключением; путают__exit__с «выполняется только при успехе», не понимая, что он вызывается и при исключении.