Контекстный менеджер with open
Контекстный менеджер with open
В предыдущем уроке мы писали open() и close() вручную. Проблема: если между ними возникнет ошибка, close() не вызовется, файл останется открытым. Конструкция with open(...) решает это автоматически — это контекстный менеджер.
Синтаксис with open
with open("notes.txt", "w", encoding="utf-8") as f:
f.write("Привет!\n")
f.write("До свидания!\n")
# Здесь файл уже закрыт — автоматически
with гарантирует, что файл будет закрыт при выходе из блока — даже если внутри произойдёт исключение. Имя переменной после as — ваш выбор; традиционно f или file.
Сравнение: с и без with
# Без with — небезопасно:
f = open("data.txt", "r", encoding="utf-8")
content = f.read()
f.close() # если f.read() вызовет ошибку — close() не выполнится
# С with — безопасно:
with open("data.txt", "r", encoding="utf-8") as f:
content = f.read()
# close() вызывается автоматически при любом исходе
Чтение с with
Все методы чтения работают внутри with так же:
# Прочитать весь файл:
with open("report.txt", "r", encoding="utf-8") as f:
text = f.read()
print(text)
# Построчно:
with open("report.txt", "r", encoding="utf-8") as f:
for line in f:
print(line.strip())
Запись с with
# Запись (перезаписать):
with open("output.txt", "w", encoding="utf-8") as f:
for i in range(1, 6):
f.write(f"Строка {i}\n")
# Дозапись:
with open("log.txt", "a", encoding="utf-8") as f:
f.write("Новое событие\n")
Несколько файлов одновременно
Python позволяет открыть несколько файлов в одном with:
with open("input.txt", "r", encoding="utf-8") as src, \
open("output.txt", "w", encoding="utf-8") as dst:
for line in src:
dst.write(line.upper())
Оба файла будут закрыты при выходе из блока.
Обработка FileNotFoundError
Если файл не существует при чтении, Python выбрасывает FileNotFoundError. Обрабатывают это через try/except (подробно в следующем модуле), но вот предварительный пример:
try:
with open("missing.txt", "r", encoding="utf-8") as f:
content = f.read()
except FileNotFoundError:
print("Файл не найден")
content = ""
Что такое контекстный менеджер
with работает не только с файлами. Любой объект, реализующий методы __enter__ и __exit__, может использоваться в блоке with. Файловые объекты Python реализуют этот протокол: при входе в блок вызывается __enter__, при выходе — __exit__, который и закрывает файл. Со временем вы встретите with для блокировок, соединений с базами данных и других ресурсов.
Проверь себя
Будет ли закрыт файл, если внутри with произойдёт ошибка?
with open("test.txt", "w", encoding="utf-8") as f:
f.write("data")
raise ValueError("что-то пошло не так")
Да — файл закроется. Контекстный менеджер гарантирует вызов __exit__ (и закрытие файла) независимо от того, было ли исключение. После этого исключение продолжит распространяться.
Итог
with open(path, mode, encoding="utf-8") as f:— открыть файл с автоматическим закрытием.- Файл закрывается при выходе из блока
withв любом случае, даже при исключении. - Можно открыть несколько файлов в одном
with, разделив запятой. with— это протокол контекстного менеджера (__enter__/__exit__); работает не только с файлами.
В следующем уроке разберём работу с путями к файлам через os.path и более удобный pathlib.