Контекстный менеджер 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.

Попробуйте интерактивную версию

Практические задачи, квизы и AI-наставник — бесплатный старт без карты

Перейти к практике