Работа с файлами в Python достаточно простая, если не забывать закрывать файлы. Но что делать, если файл не закроется из-за ошибки, которая произошла до закрытия?
file = open('data.txt', 'r') # Открываем файл
print(1 / 0, file=file) # Делим 1 на 0, что приводит к ошибке
file.close() # Сюда программа никогда не дойдёт
Для таких случаев существует менеджер контекста.
<aside> 💡 Менеджер контекста — конструкция Python, которая позволяет использовать ресурс строго в определённом блоке и автоматически освобождает его в конце этого блока.
</aside>
В нашем случае ресурсом является файл, а освобождение ресурса — это закрытие файла. В качестве другого примера ресурса можно привести подключение к базе данных.
Менеджер контекста описывается следующим образом:
with *создание_ресурса* as *название_ресурса*:
*блок_кода*
Здесь в качестве создания ресурса можно указать открытие файла, создание подключения к БД и т.п., название ресурса — это название переменной, в которую будет помещён ресурс. Посмотрим, как этот менеджер контекста работает с нашим примером:
with open('data.txt', 'r') as file: # Открываем файл с помощью менеджера
print(1 / 0, file=file) # Делим 1 на 0, что приводит к ошибке
В чём различие? Во-первых, можно увидеть, что нет строчки с file.close(). Её нет, потому что она вызывается автоматически после последней строчки в блоке менеджера. Во-вторых, файл закрылся, даже несмотря на то, что программа завершилась с ошибкой. Это можно проверить, запустив программу в интерактивной оболочке и выведя свойство file.closed.
<aside> 💡 Подробнее о том, как работает менеджер контекста и почему он способен выполнять команды даже после возникновения ошибки, рассказывается в расширенном курсе.
</aside>
В общем и целом, для работы с файлами рекомендуется именно этот способ, а не ручное закрытие файла.