Работа с файлами в 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>

В общем и целом, для работы с файлами рекомендуется именно этот способ, а не ручное закрытие файла.