Работа с файлами — одна из базовых операций в Python: чтение конфигураций, сохранение результатов, обработка логов, импорт/экспорт данных. В этой статье разберём основные способы чтения и записи файлов, особенности функции open(), методы read(), write(), а также конструкцию with, которая делает работу с файлами безопасной и предсказуемой.
Открытие файла: функция open()
Функция open(file, mode, encoding=None, ...) возвращает файловый объект, через который можно читать или писать данные.
Ключевые параметры:
file— путь к файлу (строка).mode— режим доступа.encoding— кодировка (важно для текстовых файлов).
Основные режимы
| Режим | Описание |
|---|---|
'r' |
Чтение (по умолчанию). Файл должен существовать. |
'w' |
Запись. Создаёт файл или перезаписывает существующий. |
'a' |
Дозапись. Добавляет данные в конец файла. |
'x' |
Создание нового файла. Если файл уже есть — выбрасывает ошибку. |
'b' |
Бинарный режим (добавляется к другим: 'rb', 'wb' и т. д.). |
't' |
Текстовый режим (по умолчанию вместе с 'r', 'w' и др.). |
Пример:
f = open("data.txt", "r", encoding="utf-8")
Важно: если не указать encoding, в разных ОС могут использоваться разные кодировки, что приведёт к искажению текста или ошибкам. Для кроссплатформенных скриптов всегда явно указывайте encoding="utf-8".
Чтение файла: методы read(), readline(), readlines()
read() — прочитать всё содержимое
with open("data.txt", "r", encoding="utf-8") as f: content = f.read() print(content)
Удобно для небольших файлов. Для больших файлов это может занять много памяти.
readline() — читать по одной строке
with open("data.txt", "r", encoding="utf-8") as f: while True: line = f.readline() if not line: # конец файла break print(line.rstrip()) # rstrip убирает перевод строки
readlines() — получить список строк
with open("data.txt", "r", encoding="utf-8") as f: lines = f.readlines() # lines — список, каждый элемент — строка с символом \n
Для больших файлов лучше использовать итерацию по файлу — она экономит память:
with open("large_file.txt", "r", encoding="utf-8") as f: for line in f: # обработка строки pass
Запись в файл: write()
Метод write() записывает строку. Он не добавляет перевод строки автоматически.
with open("output.txt", "w", encoding="utf-8") as f: f.write("Первая строка\n") f.write("Вторая строка\n")
Если нужно записать несколько строк, можно использовать цикл или writelines():
lines = ["Строка 1\n", "Строка 2\n", "Строка 3\n"] with open("output.txt", "w", encoding="utf-8") as f: f.writelines(lines)
Обратите внимание: writelines() не добавляет переносы строк, поэтому их нужно включать в сами строки.
Зачем нужен with: контекстный менеджер
Конструкция with (контекстный менеджер) гарантирует, что файл будет корректно закрыт даже при ошибке.
Небезопасный вариант без with:
f = open("data.txt", "r", encoding="utf-8") content = f.read() # если здесь произойдёт ошибка, файл может остаться открытым f.close()
Безопасный вариант с with:
with open("data.txt", "r", encoding="utf-8") as f: content = f.read() # файл автоматически закрыт после блока
Почему это важно:
- Гарантированный вызов
close()даже при исключениях. - Защита от утечек файловых дескрипторов (особенно в долгоживущих скриптах).
- Читаемость: сразу видно область работы с файлом.
Практические примеры
Пример 1: скопировать файл построчно (для больших файлов)
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')
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')
try: with open("config.json", "x", encoding="utf-8") as f: f.write('{"version": 1}\n') except FileExistsError: print("Файл уже существует, не перезаписываем.")
Это полезно, когда нужно избежать случайной перезаписи важных файлов.
Пример 4: прочитать CSV‑строку и сохранить обработанные данные
Допустим, входной файл prices.csv:
Товар,Цена
Яблоки,120.50
Груши,99.00
Читаем, обрабатываем и пишем в новый файл:
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'
Для картинок, архивов, исполняемых файлов используют бинарные режимы.
Чтение и запись картинки:
# Чтение 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) |
