Работа с файлами в Python

Любая переменная живёт только пока запущена программа: закрыли её — и список задач, набранный счёт, сохранённые настройки исчезли. Чтобы данные пережили перезапуск, их записывают в файл на диске, а при следующем запуске читают обратно. На этом держатся заметки, сохранения в играх, экспорт отчётов — почти любое приложение.

Открытие файлов

Для открытия файла в Python используется функция open(). Она принимает как минимум два параметра: путь к файлу и режим открытия.

Режим — это короткая строка, которая отвечает на вопрос «что мы собираемся делать с файлом». Выбрать нужно одно из трёх:

БукваЧто делает
'r'читать; файл должен существовать (режим по умолчанию)
'w'писать с нуля: создаёт файл, а существующий очищает
'a'дописывать в конец; старое содержимое остаётся на месте

Посмотрим на два самых частых режима в деле:

Python 3.13
# 'w' создаёт файл (или перезаписывает) и открывает его для записи
file = open('notes.txt', 'w')
file.write("Купить молоко")
file.close()

# 'r' открывает уже существующий файл для чтения
file = open('notes.txt', 'r')
print(file.read())
Купить молоко
file.close()

Про 'w' стоит помнить отдельно: он стирает старое содержимое молча, без предупреждения. Открыли файл с важными данными в 'w' вместо 'a' — и данных больше нет. А 'r', наоборот, требует, чтобы файл уже существовал: если его нет, Python остановит программу ошибкой FileNotFoundError.

Контекстный менеджер with

В предыдущем примере после работы с файлом вызывался close(). Разберёмся, зачем он нужен и почему в реальном коде его почти не пишут.

Открытый файл нужно закрывать: пока он открыт, он держит системные ресурсы, а записанные данные могут не попасть на диск до закрытия. Закрыть можно вручную:

Python 3.13
file = open('example.txt', 'w')
file.write("Пример текста")
file.close()

Загвоздка в том, что про close() легко забыть. А если между открытием и закрытием что-то пойдёт не так и программа прервётся, до close() дело вообще не дойдёт, и файл останется открытым.

Конструкция with снимает эту заботу: она сама закрывает файл, когда блок заканчивается, при любом исходе.

Python 3.13
with open('example.txt', 'w') as file:
    file.write("Пример текста")
# здесь файл уже закрыт автоматически
print("Файл закрыт автоматически после блока with")
Файл закрыт автоматически после блока with

Чтение из файла

После открытия файла его содержимое можно прочитать несколькими способами.

Во всех примерах ниже рядом с программой лежит файл sample.txt из трёх строк.

Чтение всего файла

main.py
1with open('sample.txt', 'r') as file:2  content = file.read()3 4print(content)5 

Запустим main.py — в выводе:

Первая строка
Вторая строка
Третья строка

Чтение файла построчно

main.py
1with open('sample.txt', 'r') as file:2  for line in file:3      print(f"Строка: {line.strip()}")4 

Запустим main.py — в выводе:

Строка: Первая строка
Строка: Вторая строка
Строка: Третья строка

Чтение всех строк в список

Цикл for line in file берёт строки по одной и не держит файл в памяти целиком. Это способ по умолчанию, особенно для больших файлов. Но иногда строки нужны все сразу: посчитать их количество, обратиться к пятой по счёту, отсортировать. Тогда пригодится readlines(), который возвращает обычный список:

main.py
1with open('sample.txt', 'r') as file:2  lines = file.readlines()3 4print(lines)5 

Запустим main.py — в выводе:

['Первая строка\n', 'Вторая строка\n', 'Третья строка']

Заметьте \n на концах элементов: readlines() режет файл по переносам строк, но сами переносы не выбрасывает. Отсюда и line.strip() в примере выше: print добавляет свой перенос к тому, что уже пришёл из файла, и без strip() между строками появились бы пустые.

Запись в файл

Записывать данные в файл можно несколькими способами:

Запись строки

Python 3.13
with open('output.txt', 'w') as file:
    file.write("Привет, мир!\n")
    file.write("Python - отличный язык программирования.")

# Проверим, что записалось
with open('output.txt', 'r') as file:
    content = file.read()
    print("Содержимое файла после записи:")
Содержимое файла после записи:
    print(content)
Привет, мир!
Python - отличный язык программирования.

Запись нескольких строк

Python 3.13
# Запись списка строк в файл
lines = ["Первая строка", "Вторая строка", "Третья строка"]

with open('lines.txt', 'w') as file:
    for line in lines:
        file.write(line + '\n')

# Проверим, что записалось
with open('lines.txt', 'r') as file:
    content = file.read()
    print("Содержимое файла lines.txt:")
Содержимое файла lines.txt:
    print(content)
Первая строка
Вторая строка
Третья строка

Добавление данных в конец файла

Рядом лежит output.txt с двумя строками — режим 'a' допишет в его конец, ничего не стирая:

main.py
1with open('output.txt', 'a') as file:2  file.write("3Эта строка добавлена позже.")4 5with open('output.txt', 'r') as file:6  print(file.read())7 

Запустим main.py — в выводе:

Привет, мир!
Python - отличный язык программирования.
Эта строка добавлена позже.

Обработка исключений при работе с файлами

При работе с файлами могут возникать ошибки: файла нет на месте, не хватает прав на доступ, на диске кончилось место.

Перехватывать такие ошибки и реагировать на них умеет конструкция try/except (ей посвящён отдельный урок дальше в курсе). Здесь достаточно увидеть её в действии на файлах: блок try пробует выполнить операцию, а except ловит конкретную ошибку, если она случилась.

Python 3.13
# Обработка возможных ошибок при открытии файла
try:
    with open('несуществующий_файл.txt', 'r') as file:
        content = file.read()
except FileNotFoundError:
    print("Ошибка: Файл не найден!")
Ошибка: Файл не найден!

Работа с путями к файлам

До сих пор мы писали имя файла как есть: open('notes.txt'). Python ищет такой файл в текущем каталоге — там, откуда запущена программа.

Если файл лежит в соседней папке, нужен путь. Склеивать его строками рискованно: на macOS и Linux части разделяет /, а на Windows \. Написанный вручную путь сломается при переезде на другую систему.

Поэтому пути собирают модулем pathlib из стандартной библиотеки.

Путь в pathlib — не строка, а объект: части соединяются оператором /, а имя, расширение и проверка существования доступны прямо у объекта. Читается такой код близко к тому, как путь выглядит.

В песочнице текущий каталог — /home/pyodide; на вашем компьютере путь будет другим.

Python 3.13
from pathlib import Path

# Текущий каталог
current_path = Path.cwd()
print(f"Текущий каталог: {current_path}")
Текущий каталог: /home/pyodide
# Создание пути
data_file = current_path / 'data' / 'info.txt'
print(f"Путь к файлу: {data_file}")
Путь к файлу: /home/pyodide/data/info.txt
# Получение имени файла и расширения
document_path = Path("path/to/document.pdf")
print(f"Имя файла: {document_path.stem}, расширение: {document_path.suffix}")
Имя файла: document, расширение: .pdf

Проверка существования — метод exists(): он отвечает, есть ли по пути настоящий файл. Ниже sample.txt лежит рядом с программой, а missing.txt — нет:

main.py
1from pathlib import Path2 3print(Path('sample.txt').exists())4print(Path('missing.txt').exists())5 

Запустим main.py — в выводе:

True
False

Проверка понимания

Что случится с содержимым, если открыть существующий файл в режиме 'w'?

В следующих уроках мы углубимся в работу с конкретными типами файлов, такими как текстовые файлы, CSV, JSON и другие.