Как читать и писать файлы в Python: open(), read(), write() и зачем нужен with

Работа с файлами — одна из базовых операций в Python: чтение конфигураций, сохранение результатов, обработка логов, импорт/экспорт данных. В этой статье разберём основные способы чтения и записи файлов, особенности функции open(), методы read(), write(), а также конструкцию with, которая делает работу с файлами безопасной и предсказуемой.


Открытие файла: функция open()

Функция open(file, mode, encoding=None, ...) возвращает файловый объект, через который можно читать или писать данные.

Ключевые параметры:

  • file — путь к файлу (строка).
  • mode — режим доступа.
  • encoding — кодировка (важно для текстовых файлов).

Основные режимы

Режим Описание
'r' Чтение (по умолчанию). Файл должен существовать.
'w' Запись. Создаёт файл или перезаписывает существующий.
'a' Дозапись. Добавляет данные в конец файла.
'x' Создание нового файла. Если файл уже есть — выбрасывает ошибку.
'b' Бинарный режим (добавляется к другим: 'rb', 'wb' и т. д.).
't' Текстовый режим (по умолчанию вместе с 'r', 'w' и др.).

Пример:

python
f = open("data.txt", "r", encoding="utf-8")

Важно: если не указать encoding, в разных ОС могут использоваться разные кодировки, что приведёт к искажению текста или ошибкам. Для кроссплатформенных скриптов всегда явно указывайте encoding="utf-8".


Чтение файла: методы read(), readline(), readlines()

read() — прочитать всё содержимое

python
with open("data.txt", "r", encoding="utf-8") as f:
    content = f.read()
print(content)

Удобно для небольших файлов. Для больших файлов это может занять много памяти.

readline() — читать по одной строке

python
with open("data.txt", "r", encoding="utf-8") as f:
    while True:
        line = f.readline()
        if not line:  # конец файла
            break
        print(line.rstrip())  # rstrip убирает перевод строки

readlines() — получить список строк

python
with open("data.txt", "r", encoding="utf-8") as f:
    lines = f.readlines()
# lines — список, каждый элемент — строка с символом \n

Для больших файлов лучше использовать итерацию по файлу — она экономит память:

python
with open("large_file.txt", "r", encoding="utf-8") as f:
    for line in f:
        # обработка строки
        pass

Запись в файл: write()

Метод write() записывает строку. Он не добавляет перевод строки автоматически.

python
with open("output.txt", "w", encoding="utf-8") as f:
    f.write("Первая строка\n")
    f.write("Вторая строка\n")

Если нужно записать несколько строк, можно использовать цикл или writelines():

python
lines = ["Строка 1\n", "Строка 2\n", "Строка 3\n"]
with open("output.txt", "w", encoding="utf-8") as f:
    f.writelines(lines)

Обратите внимание: writelines() не добавляет переносы строк, поэтому их нужно включать в сами строки.


Зачем нужен with: контекстный менеджер

Конструкция with (контекстный менеджер) гарантирует, что файл будет корректно закрыт даже при ошибке.

Небезопасный вариант без with:

python
f = open("data.txt", "r", encoding="utf-8")
content = f.read()
# если здесь произойдёт ошибка, файл может остаться открытым
f.close()

Безопасный вариант с with:

python
with open("data.txt", "r", encoding="utf-8") as f:
    content = f.read()
# файл автоматически закрыт после блока

Почему это важно:

  • Гарантированный вызов close() даже при исключениях.
  • Защита от утечек файловых дескрипторов (особенно в долгоживущих скриптах).
  • Читаемость: сразу видно область работы с файлом.

Практические примеры

Пример 1: скопировать файл построчно (для больших файлов)

python
src = "input.txt"
dst = "output.txt"
 
with open(src, "r", encoding="utf-8") as fin, open(dst, "w", encoding="utf-8") as fout:
    for line in fin:
        fout.write(line)

Здесь два файла открыты в одном with — это удобно и безопасно.

Пример 2: добавить лог в файл (режим 'a')

python
log_entry = "2026-08-01 12:34:56 — Пользователь вошёл в систему\n"
 
with open("app.log", "a", encoding="utf-8") as f:
    f.write(log_entry)

Режим 'a' добавляет запись в конец, не стирая старые логи.

Пример 3: создать файл только если его нет (режим 'x')

python
try:
    with open("config.json", "x", encoding="utf-8") as f:
        f.write('{"version": 1}\n')
except FileExistsError:
    print("Файл уже существует, не перезаписываем.")

Это полезно, когда нужно избежать случайной перезаписи важных файлов.

Пример 4: прочитать CSV‑строку и сохранить обработанные данные

Допустим, входной файл prices.csv:

text
Товар,Цена
Яблоки,120.50
Груши,99.00

Читаем, обрабатываем и пишем в новый файл:

python
input_file = "prices.csv"
output_file = "prices_fixed.csv"
 
with open(input_file, "r", encoding="utf-8") as fin, \
     open(output_file, "w", encoding="utf-8") as fout:
 
    # Записываем заголовок
    fout.write("Товар,Цена_руб\n")
 
    # Пропускаем первую строку (заголовок)
    next(fin)
 
    for line in fin:
        line = line.strip()
        if not line:
            continue
        parts = line.split(",")
        if len(parts) != 2:
            continue
 
        name, price_str = parts
        try:
            price = float(price_str.replace(",", "."))
            # Допустим, конвертируем в рубли (тут просто пример)
            price_rub = price * 1.0  # без конвертации, для примера
            fout.write(f"{name},{price_rub:.2f}\n")
        except ValueError:
            print(f"Пропущена некорректная строка: {line}")

Бинарные файлы: режимы с 'b'

Для картинок, архивов, исполняемых файлов используют бинарные режимы.

Чтение и запись картинки:

python
# Чтение
with open("image.png", "rb") as f:
    data = f.read()  # data — bytes
 
# Запись
with open("copy.png", "wb") as f:
    f.write(data)

Бинарные данные нельзя обрабатывать как текст: не используйте .replace(), не пытайтесь декодировать без необходимости.


Шпаргалка по режимам и действиям

Задача Режим Метод
Прочитать весь файл 'r' read()
Читать построчно 'r' итерация по файлу или readline()
Записать новый файл 'w' write() или writelines()
Дописать в конец 'a' write()
Создать, но не перезаписывать 'x' write() + обработка FileExistsError
Работать с бинарными данными 'rb' / 'wb' read(), write()bytes)

Добавить комментарий