Обработка файлов Python: чтение, запись, CSV, JSON и pathlib с примерами

  1. Главная
  2. Блог
  3. Разработка программного обеспечения

Разработка программного обеспечения

Обработка файлов Python: Чтение, запись, CSV, JSON и pathlib с примерами

Почти каждый настоящий скрипт читает или записывает файл. Узнайте, как безопасно открывать файлы, выбирать правильный режим, обрабатывать CSV и JSON, работать с путями с помощью pathlib и избегать ошибок, приводящих к стиранию ваших данных.

9 мин чтения
Обработка файлов Python: чтение, запись, CSV, JSON и pathlib с примерами

Главное

  • Всегда открывайте файлы с блоком with, чтобы они закрывались автоматически.
  • Режим "w" удаляет существующий файл. Используйте "a", чтобы добавить к одному, или "x", чтобы отказаться от перезаписи.
  • Перебирайте файловый объект в цикле, чтобы читать большие файлы, не загружая все в память.
  • Передайте encoding="utf-8" явно и отдайте предпочтение pathlib для построения путей.

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

В этом руководстве рассматриваются текстовые файлы, CSV, JSON, двоичные данные и пути с упором на безопасные привычки. Мы запускали эти примеры на Python 3.13 во временной папке, и показанный результат получен в результате этого запуска.

Открывайте файлы с помощью open() и с помощью

Встроенная функция open() возвращает файловый объект. Используйте его внутри блока with:

with open("notes.txt", "w", encoding="utf-8") as file:
    file.write("first line\n")
    file.write("second line\n")

print(file.closed)

# True

Когда блок заканчивается, Python закрывает файл, даже если внутри него произошла ошибка. Без with вам придется вызывать close() самостоятельно, и исключение может пропустить эту строку. Использование файла после его закрытия вызывает ошибку:

file.read()

# ValueError: I/O operation on closed file.

Режимы файлов

Второй аргумент open() говорит о том, что вы планируете делать:

Режим Значение Если файл существует Если это не так
р Чтение (по умолчанию) Открывает его Ошибка
ш Написать Сначала стирает Создает это
а Добавить Добавляет в конец Создает это
х Эксклюзивное создание Ошибка Создает это
р+ Читай и пиши Открывает его Ошибка

Добавьте b для двоичных данных, как в "rb" или "wb". Текст используется по умолчанию, его также можно записать явно как t.

Напишите и добавьте

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

with open("notes.txt", "a", encoding="utf-8") as file:
    file.write("third line\n")

Сравните это с режимом "w", в котором наши три строки были заменены одной без какого-либо предупреждения:

with open("notes.txt", "w", encoding="utf-8") as file:
    file.write("replaced\n")

# notes.txt now contains only: replaced

Если вы не должны что-то перезаписывать, используйте "x". В нашем тесте он вызвал FileExistsError, поскольку notes.txt уже существовало.

Чтение файла

Существует несколько способов чтения, правильный выбор зависит от размера файла:

Подход Возврат Лучшее для
file.read() Одна строка со всем Маленькие файлы
file.readline() Следующая строка Чтение заголовка
file.readlines() Список строк Небольшие файлы, которые вам нужны в виде списка
для строки в файле По одной строке за раз Любой размер, особенно большие файлы
with open("notes.txt", encoding="utf-8") as file:
    print(repr(file.read()))

# 'first line\nsecond line\n'

with open("notes.txt", encoding="utf-8") as file:
    for line in file:
        print(line.strip())

# first line
# second line
# third line

Обратите внимание на символы \n в необработанной строке. strip() удаляет их. Файловый объект также запоминает свою позицию, поэтому чтение продолжается с того места, где оно было остановлено:

with open("notes.txt", encoding="utf-8") as file:
    print(file.readline().strip())
    print(file.readlines())

# first line
# ['second line\n', 'third line\n']

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

Обработка ошибок файлов

Файлы могут отсутствовать, быть заблокированными или нечитаемыми, поэтому запланируйте следующее:

try:
    with open("missing.txt", encoding="utf-8") as file:
        data = file.read()
except FileNotFoundError as error:
    print(error)

# [Errno 2] No such file or directory: 'missing.txt'
Исключение Типичная причина
Филенотфаундеррор Путь не существует
FileExistsError Режим x для существующего файла
Ошибка разрешения Не разрешено или заблокировано в Windows
Исадиректориеррор Путь представляет собой папку
Юникодекодееррор Использована неправильная кодировка

Попробуйте открыть файл и обнаружить ошибку, вместо того, чтобы сначала проверять с помощью exists(), так как между проверкой и открытием файл может исчезнуть. Наше руководство по обработке исключений Python описывает этот подход.

CSV-файлы

Не разделяйте строки CSV самостоятельно запятыми, поскольку значения в кавычках могут содержать запятые. Эти правила обрабатываются стандартным модулем csv. DictWriter и DictReader — наиболее читаемые варианты:

import csv

with open("orders.csv", "w", newline="", encoding="utf-8") as file:
    writer = csv.DictWriter(file, fieldnames=["id", "customer", "total"])
    writer.writeheader()
    writer.writerow({"id": 1, "customer": "Asha", "total": 1200})
    writer.writerow({"id": 2, "customer": "Ben", "total": 300})

with open("orders.csv", newline="", encoding="utf-8") as file:
    rows = list(csv.DictReader(file))

print(rows[0])
print(sum(int(r["total"]) for r in rows))

# {'id': '1', 'customer': 'Asha', 'total': '1200'}
# 1500

Две детали имеют значение. Передайте newline="" при открытии файлов CSV, как рекомендует документация, чтобы предотвратить появление пустых строк в Windows. И каждое значение возвращается в виде строки, четных чисел, поэтому нам понадобилось int() в сумме. Для работы с большими объемами данных лучше подойдет такая библиотека, как pandas.

JSON-файлы

JSON — это обычный формат конфигурации и данных API. Он аккуратно сопоставляется с словарями Python и содержит:

import json

config = {"debug": True, "retries": 3, "hosts": ["a", "b"]}

with open("config.json", "w", encoding="utf-8") as file:
    json.dump(config, file, indent=2)

with open("config.json", encoding="utf-8") as file:
    print(json.load(file)["retries"])

# 3

Помните об именах: dump и load работают с файлами, а dumps и loads — со строками. Такие типы, как даты, невозможно сохранить напрямую, поэтому вам необходимо сначала преобразовать их в строки.

Работайте с путями с помощью pathlib

Склеивание путей со строками не работает в разных операционных системах. Стандартный модуль pathlib обрабатывает разделители и предлагает удобные сочетания клавиш:

from pathlib import Path

path = Path("data") / "reports" / "summary.txt"
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("all good\n", encoding="utf-8")

print(path.read_text(encoding="utf-8").strip())   # all good
print(path.suffix, path.stem, path.exists())      # .txt summary True
print(sorted(p.name for p in Path(".").glob("*.csv")))
# ['orders.csv']
Задача библиотека путей
Присоединиться к путям Путь("a")/"b.txt"
Создание папок path.mkdir(parents=True, Exist_ok=True)
Прочитать или написать весь текст read_text(), write_text()
Найти файлы glob("*.csv"), rglob("*.py")
Удалить файл path.unlink()
Получить папку текущего скрипта Path(__file__).parent

Последнее решает обычную головную боль. Относительные пути определяются от того места, где вы запустили сценарий, а не от того, где он находится, поэтому построение путей из Path(__file__).parent позволяет избежать многих сюрпризов, связанных с тем, что файл не найден.

Бинарные файлы

Изображения, PDF-файлы и ZIP-файлы не являются текстом. Откройте их с помощью b, и вы сможете читать и писать bytes без какого-либо кодирования:

with open("pixel.bin", "wb") as file:
    file.write(bytes([255, 0, 128]))

with open("pixel.bin", "rb") as file:
    print(file.read())

# b'\xff\x00\x80'

Сафер пишет

Если программа выйдет из строя на полпути записи важного файла, вы можете получить испорченный результат. Обычное решение — сначала записать временный файл, а затем заменить его на место:

temp = Path("settings.tmp")
temp.write_text("new", encoding="utf-8")
temp.replace("settings.txt")

print(Path("settings.txt").read_text(), temp.exists())

# new False

replace() перезаписывает место назначения. В одной и той же файловой системе переименование обычно является атомарным, поэтому читатели видят либо старый файл, либо новый, а не наполовину написанную смесь.

Совет. Никогда не создавайте пути к файлам непосредственно на основе пользовательского ввода, не проверив их. Значение типа ../../secrets.txt может достигать файлов за пределами вашей предполагаемой папки. Это известно как уязвимость обхода пути.

Практический пример: суммирование журнала

Этот короткий сценарий объединяет несколько идей. Он читает журнал по одной строке за раз, поэтому его размер не имеет значения, подсчитывает каждый уровень с помощью Counter и записывает сводку в новый файл:

from collections import Counter

counts = Counter()
with open("app.log", encoding="utf-8") as file:
    for line in file:
        counts[line.split()[0]] += 1

with open("summary.txt", "w", encoding="utf-8") as out:
    for level, total in counts.most_common():
        out.write(f"{level}: {total}\n")

# summary.txt
# ERROR: 2
# INFO: 2
# WARN: 1

В нашем образце журнала было пять строк. Пустая строка будет разрывать line.split()[0], поэтому реальные сценарии должны сначала пропускать пустые строки.

Распространенные ошибки

  • Используйте "w", когда вы имели в виду "a". Ваши существующие данные сразу же открываются, даже если вы никогда ничего не пишете.
  • Кодировка пропущена. Значение по умолчанию зависит от системы, поэтому сценарий, работающий в Linux, может не работать в Windows с акцентированным текстом или эмодзи.
  • Вызов read() для огромных файлов. Это может исчерпать память, поэтому вместо этого перебирайте строки.
  • Если забыть int() о значениях CSV. "10" + "20" дает "1020".
  • Отсутствует newline="" для CSV. В Windows могут появиться неожиданные пустые строки.
  • Не тестируется файловый код. Используйте приспособление pytest tmp_path, чтобы тесты никогда не касались реальных файлов. См. наше руководство по pytest.

Итоги

Несколько привычек охватывают здесь почти все: используйте with, установите кодировку, дважды подумайте о "w" и позвольте csv, json и pathlib выполнять сложную часть. Для практики напишите небольшой скрипт, который читает CSV, суммирует один столбец и сохраняет сводку JSON в новую папку.

Часто задаваемые вопросы

Как прочитать файл построчно в Python?

Откройте его в блоке with и переберите файловый объект. Он читает по одной строке за раз, поэтому хорошо работает даже с очень большими файлами.

В чем разница между w и режимом?

Режим w удаляет все существующее содержимое сразу после открытия файла. Режим a сохраняет существующее содержимое и добавляет новые данные в конец файла.

Почему я должен использовать with, чтобы открыть файл?

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

Как проверить, существует ли файл в Python?

Используйте Path(“name.txt”).exists() из pathlib. Если вы планируете открыть его сразу после этого, перехват FileNotFoundError обычно более надежен, чем предварительная проверка.

Почему в моем CSV-файле в Windows есть пустые строки?

Вероятно, вы открыли файл без символа новой строки=””. Модуль csv сам управляет окончаниями строк, поэтому передайте этот аргумент, чтобы избежать лишних пустых строк.

Продолжайте учиться

Работайте с Stack Quora

Нужна помощь с тестированием, WordPress или SEO?

Мы помогаем командам выпускать лучшее программное обеспечение и развивать свои сайты. Расскажите нам, над чем вы работаете, и мы предложим четкий следующий шаг.

Продолжайте читать

Больше руководств по тестирование, искусственный интеллект и современные разработки

Понравилась эта статья? Выберите тему и сразу приступайте к нашим новейшим руководствам.

Искусственный интеллект

Объяснение галлюцинаций искусственного интеллекта: почему языковые модели все выдумывают и как их уменьшить

Галлюцинации ИИ объяснили: что это такое, почему языковые модели их создают, распространенные типы, как уменьшить их с помощью заземления и подсказо…

Читать статью →
DevOps

Объяснение переменных среды: файлы .env, секреты и правильно выполненная конфигурация

Переменные среды объясняются на примерах Python, которые мы запускали: их чтение и установка, почему каждое значение является строкой, файлы .env, н…

Читать статью →
Разработка ПО

Объяснение ограничения скорости API: алгоритмы, заголовки и обработка ошибок 429

Ограничение скорости API объясняется с помощью проведенного нами моделирования: сегмент токенов, фиксированное окно, скользящее окно, 429 ответов, з…

Читать статью →
Автоматизация тестирования

Издевательство в Python: unittest.mock, патч и ошибки, из-за которых тесты лгут

Издевательство на Python с помощью unittest.mock, протестировано: Mock и return_value, Side_effect, исправление использования имени, спецификация и …

Читать статью →
Тестирование ПО

Объяснение покрытия кода: покрытие линий или ветвей и что на самом деле означает 100%

Покрытие кода объяснено с помощью реального запуска покрытия.py: покрытие строк, ветвей и условий, чтение отчета, почему 100%-ное покрытие все еще м…

Читать статью →
Базы данных и SQL

DELETE, TRUNCATE и DROP в SQL: различия, откат и когда использовать каждый из них

Объяснение DELETE, TRUNCATE и DROP на примере протестированного SQL: что каждый из них удаляет, откат, триггеры, сброс идентификаторов, скорость и ч…

Читать статью →
Базы данных и SQL

Объяснение представлений SQL: создавайте, используйте и избегайте ловушек, с примерами

Представления SQL, объясненные с помощью запросов, которые мы выполняли: создание представления, результаты в реальном времени, скрытие столбцов, пр…

Читать статью →
Разработка ПО

Интерфейс TypeScript и тип: реальные различия, протестированные с помощью компилятора

Интерфейс TypeScript против типа, проверенный реальным компилятором: что могут делать оба, что может делать только один, слияние объявлений, расшире…

Читать статью →
Разработка ПО

Объяснение Python *args и **kwargs: гибкие функции с понятными примерами

Python *args и **kwargs, объясненные с помощью кода, который мы запускали: упаковка и распаковка, порядок параметров, аргументы только по ключевым с…

Читать статью →
Разработка ПО

Лямбда-функции Python: синтаксис, реальное использование и когда их не следует использовать

Лямбда-функции Python, объясненные с помощью кода, который мы запускали: синтаксис, сортировка с помощью ключа, карты и фильтра, замыкания, ловушка …

Читать статью →
Искусственный интеллект

Что такое ИИ-агенты? Как они работают: можно запустить простой цикл агента

Что такое агенты ИИ? Простое руководство по циклу агента, инструментам, памяти и ограничениям, с небольшим циклом Python, который мы запустили, реал…

Читать статью →
DevOps

Мониторинг и наблюдаемость: реальная разница с журналами, метриками и трассировками

Объяснение мониторинга и наблюдаемости: известные и неизвестные сбои, журналы, метрики и трассировки, пошаговое руководство по инцидентам при оформл…

Читать статью →
DevOps

Docker Volumes против Bind Mounts: правильное сохранение данных контейнера

Объяснение томов Docker и монтирования привязки: почему исчезают данные контейнера, именованные тома, монтирование привязки, tmpfs, примеры создания…

Читать статью →
Автоматизация тестирования

TDD против BDD: ключевые различия, одна функция, созданная для обоих способов, и когда использовать каждый

TDD и BDD объясняются с помощью одной функции скидки, созданной в обоих направлениях: красно-зеленый рефакторинг с кодом, который мы запускали, сцен…

Читать статью →
Тестирование ПО

Пользовательское приемочное тестирование (UAT): процесс, контрольный список и реальные примеры

Приемочное тестирование пользователей объяснило: кто его проводит, чем оно отличается от контроля качества, семиэтапный процесс, шаблон тестового сц…

Читать статью →
Базы данных и SQL

Объяснение значений NULL в SQL: IS NULL, COALESCE, NULLIF и ловушки, которых следует избегать

Значения SQL NULL объяснены с помощью запросов, которые мы выполнили: трехзначная логика, IS NULL, COALESCE, NULLIF, как агрегаты, соединения и сорт…

Читать статью →
Базы данных и SQL

Оператор SQL CASE WHEN: синтаксис, реальные примеры и распространенные ошибки

SQL CASE WHEN объяснен с помощью запросов, которые мы выполняли: простые формы и формы для поиска, порядок условий, повороты с помощью SUM, трюки CO…

Читать статью →
Разработка ПО

Что такое JWT? Веб-токены JSON, объясненные на рабочем примере

Что такое JWT? Объяснение JSON Web Tokens: три части: токен, созданный и измененный в коде, который мы запускали, JWT и сеансы, хранилище, токены об…

Читать статью →
Разработка ПО

Объяснение цикла событий JavaScript: стек вызовов, микрозадачи и таймеры с примерами

Цикл событий JavaScript объясняется с помощью кода, который мы запускали: стек вызовов, очереди задач и микрозадач, почему setTimeout 0 не является …

Читать статью →
Разработка ПО

Генераторы Python и объяснение доходности: экономьте память с помощью реальных примеров

Генераторы Python и доходность, объясненные с помощью кода, который мы запускали: как они приостанавливаются и возобновляются, измеряют экономию пам…

Читать статью →
Искусственный интеллект

Что такое вложения? Простое объяснение векторов и косинусного сходства

Что такое вложения? Простое руководство по векторам, косинусному подобию и семантическому поиску с небольшим примером, который мы использовали, общи…

Читать статью →
DevOps

Сине-зеленое и канареечное развертывание: различия, компромиссы и как выбрать

Объяснение сине-зеленого и канареечного развертывания: как каждый из них работает, стоимость, риски и откат, стабильное группирование пользователей,…

Читать статью →
Автоматизация тестирования

Ненадежные тесты: что их вызывает и как их исправить навсегда

Ненадежные тесты объясняются на демонстрациях, которые мы запускали: основные причины, способы подтверждения и диагностики, правильные исправления в…

Читать статью →
Тестирование ПО

Нагрузочное тестирование и стресс-тестирование: различия, метрики и примеры k6

Объяснение нагрузочного и стресс-тестирования: что доказывает каждое из них, тесты на всплески и выдержки, важные метрики, почему средние значения в…

Читать статью →
Тестирование ПО

Тестовый пример и тестовый сценарий: ключевые различия, примеры и когда использовать каждый

Объяснение тестового случая и тестового сценария: четкие определения, параллельная таблица, одна функция сброса пароля, взятая из сценариев в случаи…

Читать статью →
Базы данных и SQL

Оптимизация SQL-запросов: чтение планов выполнения и исправление медленных запросов с указанием времени

Оптимизация SQL-запросов проверена на миллионе строк: читайте планы выполнения, добавляйте правильные индексы, исправляйте неразмещаемые фильтры, ис…

Читать статью →
Базы данных и SQL

SQL UNION против UNION ALL: различия, примеры и проверка производительности

SQL UNION и UNION ALL объяснены с помощью запросов, которые мы выполнили: дубликаты, правила, которым следуют оба, реальная ошибка данных, измеренна…

Читать статью →
Разработка ПО

Учебное пособие по API JavaScript Fetch: GET, POST, обработка ошибок и тайм-ауты

Учебное пособие по API JavaScript Fetch, протестированное на локальном сервере: GET и POST, почему не выдается ошибка 404, многоразовый помощник, ст…

Читать статью →
Разработка ПО

Обработка файлов Python: чтение, запись, CSV, JSON и pathlib с примерами

Обработка файлов Python объясняется с помощью кода, который мы запускали: открытые режимы, чтение больших файлов, CSV, JSON, pathlib, двоичные файлы…

Читать статью →
Разработка ПО

Классы и объекты Python: учебник ООП с реальными примерами

Классы и объекты Python, объясненные с помощью кода, который мы запускали: __init__, методы, атрибуты класса и экземпляра, наследование, свойства, м…

Читать статью →
Искусственный интеллект

Что такое большая языковая модель? Как работают LLM, объяснено без шумихи

Что такое большая языковая модель? LLM объясняется простым языком: токены, встраивания, внимание, обучение, температурные и контекстные окна, крошеч…

Читать статью →
DevOps

Команды Linux для начинающих: основное руководство по терминалу с примерами

Команды Linux для начинающих, сгруппированные по задачам: навигация, файлы, просмотр журналов, grep, каналы, разрешения, процессы и архивы, с практи…

Читать статью →
Автоматизация тестирования

Selenium vs Playwright: ключевые различия, сравнение кода и что выбрать

Сравнение Selenium и Playwright: архитектура, ожидание, поддержка браузера и языка, отладка, одинаковый тест в обоих инструментах, советы по миграци…

Читать статью →
Тестирование ПО

Разделение эквивалентности: метод проектирования тестов, объясненный на рабочих примерах

Объяснение эквивалентного разделения: как найти действительные и недействительные разделы, рабочие примеры для возрастов, паролей и купонов, проведе…

Читать статью →
Тестирование ПО

Серьезность и приоритет в тестировании программного обеспечения: различия, матрица и реальные примеры

Объяснение серьезности и приоритета при тестировании программного обеспечения: четкие определения, четырехсторонняя матрица с примерами, шкалы уровн…

Читать статью →
Базы данных и SQL

Учебное пособие по подзапросам SQL: типы, коррелирующие подзапросы и EXISTS с примерами

Руководство по подзапросам SQL с выполненными нами запросами: скалярные подзапросы, IN, FROM и SELECT, коррелированные подзапросы, EXISTS, ловушка N…

Читать статью →
Базы данных и SQL

Объяснение транзакций SQL и ACID: COMMIT, ROLLBACK и уровни изоляции

Транзакции SQL и ACID, объясненные с помощью банковского перевода, который мы выполнили: COMMIT, ROLLBACK, точки сохранения, блокировки, уровни изол…

Читать статью →
Разработка ПО

Git merge vs rebase: отличия, примеры и когда что использовать

Git merge vs rebase с реальным выводом log, сравнительной таблицей, золотым правилом rebase и безопасным рабочим процессом для команды.

Читать статью →
Разработка ПО

Генераторы списков в Python: синтаксис, примеры и когда их избегать

Генераторы списков в Python: синтаксис, фильтры, if-else, вложенные циклы, измеренное время и случаи, когда обычный цикл for лучше.

Читать статью →
Базы данных и SQL

SQL JOIN: объяснение с примерами (Inner, Left, Right, Full)

Разберите SQL JOIN шаг за шагом на примерах таблиц и запросов: INNER, LEFT, RIGHT, FULL, CROSS и SELF, а также частые ошибки и советы по производите…

Читать статью →