Работа с файлами в Python: как сохранить данные

Раздел: Работа с данными -> Ввод-вывод данных

Сохранение данных в файл в Python

Наиболее эффективный способ записи данных в файл

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

Пример записи строки в текстовый файл:


data = "Привет, мир!"
with open("example.txt", "w", encoding="utf-8") as f:
    f.write(data)

Python сохранить (сохранение данных в файл)

Пояснение: open() принимает имя файла и режим ("w" - запись, "a" - добавление, "x" - создание). Параметр encoding задает кодировку. Менеджер контекста with автоматически вызывает f.close() по завершении блока.

Типичные ошибки и их решения

  • UnicodeEncodeError - возникает, если в данных есть символы, не представимые в выбранной кодировке. Решение: указать encoding="utf-8", которая поддерживает все символы Юникода.
  • FileNotFoundError - если путь к файлу не существует. Решение: предварительно создать каталог с помощью os.makedirs() или использовать обработку исключений.
  • PermissionError - недостаточно прав для записи. Решение: проверить права доступа или запустить скрипт с соответствующими привилегиями.

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

Если требуется сохранить список строк, каждая строка должна заканчиваться символом перевода строки. Для этого используется метод writelines() или цикл с write().


lines = ["Первая строка", "Вторая строка", "Третья строка"]
# Добавляем символы новой строки
lines_with_newline = [line + "\n" for line in lines]
with open("multiline.txt", "w", encoding="utf-8") as f:
    f.writelines(lines_with_newline)

Также можно использовать цикл:


with open("multiline.txt", "w", encoding="utf-8") as f:
    for line in lines:
        f.write(line + "\n")

Проблема: отсутствие пустой строки в конце файла

Метод writelines() не добавляет символы перевода строки автоматически. Без их явного указания все строки будут записаны подряд. Решение: перед записью дополнить каждую строку символом \n.

Как сохранить табличные данные в CSV?

Для работы с CSV удобно использовать встроенный модуль csv. Он позволяет корректно обрабатывать разделители, кавычки и специальные символы.


import csv

data = [
    ["Имя", "Возраст", "Город"],
    ["Анна", 25, "Москва"],
    ["Иван", 30, "Санкт-Петербург"]
]

with open("people.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.writer(f, delimiter=";")
    writer.writerows(data)

Параметр newline="" предотвращает появление пустых строк между записями. Разделитель delimiter=";" используется для совместимости с некоторыми программами.

Ошибка: лишние пустые строки в CSV

Если не указать newline="", то на Windows между строками могут появиться пустые строки. Решение: всегда добавлять newline="" при открытии файла для записи CSV.

Как сохранить словарь или список в JSON?

Формат JSON идеально подходит для хранения структурированных данных. Модуль json позволяет сериализовать объекты Python в строку и записать её в файл.


import json

data = {
    "name": "Анна",
    "age": 25,
    "city": "Москва",
    "hobbies": ["чтение", "плавание"]
}

with open("data.json", "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=4)

Параметр ensure_ascii=False сохраняет кириллические символы в читаемом виде, а indent=4 форматирует вывод с отступами для удобства чтения.

Проблема: потеря типа данных

Не все объекты Python могут быть сериализованы в JSON (например, datetime, set). При попытке записи такого объекта возникает TypeError. Решение: преобразовать данные в сериализуемый формат или использовать default параметр в json.dump().

Как сериализовать произвольный объект Python в файл?

Для сохранения сложных объектов (например, экземпляров классов) используется модуль pickle. Он создаёт бинарное представление объекта.


import pickle

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

person = Person("Анна", 25)

with open("person.pkl", "wb") as f:
    pickle.dump(person, f)

Режим "wb" означает запись в бинарном режиме. Для чтения используется pickle.load().

Ошибка: небезопасность pickle

Модуль pickle не является безопасным при загрузке данных из ненадёжных источников - злоумышленник может внедрить вредоносный код. Решение: применять pickle только для доверенных данных, а для обмена данными между программами использовать JSON или другие форматы.

Как записать данные с форматированием (f-строки)?

F-строки упрощают форматирование вывода. Их можно использовать в сочетании с обычной записью.


name = "Анна"
age = 25
with open("info.txt", "w", encoding="utf-8") as f:
    f.write(f"Имя: {name}, Возраст: {age}\n")

Также можно записать многострочный блок:


with open("info.txt", "w", encoding="utf-8") as f:
    print(f"Имя: {name}", file=f)
    print(f"Возраст: {age}", file=f)

Функция print() с аргументом file позволяет выводить данные напрямую в файл, автоматически добавляя перевод строки.

Как правильно указать кодировку при записи?

Кодировка явно задаётся параметром encoding в функции open(). Если опустить этот параметр, используется кодировка по умолчанию, которая зависит от операционной системы (часто cp1251 на Windows или UTF-8 на Linux).


# Явное указание UTF-8
with open("example_utf8.txt", "w", encoding="utf-8") as f:
    f.write("Текст на русском")

# Явное указание cp1251 (Windows-1251)
with open("example_cp1251.txt", "w", encoding="cp1251") as f:
    f.write("Текст на русском")

Проблема: несовместимость кодировок при переносе файлов

Файл, записанный в cp1251, может некорректно отображаться в средах, ожидающих UTF-8. Решение: придерживаться UTF-8 как универсального стандарта, особенно при обмене данными между разными системами.

Расширенные примеры сохранения данных в файл

1. Запись лога с временными метками

Пример

import datetime

def log_message(message, filename="app.log"):
    timestamp = datetime.datetime.now().isoformat()
    with open(filename, "a", encoding="utf-8") as f:
        f.write(f"[{timestamp}] {message}\n")

log_message("Запуск приложения")
log_message("Обработано 10 запросов")
Содержимое файла app.log:
[2025-03-28T14:30:00.123456] Запуск приложения
[2025-03-28T14:31:15.789012] Обработано 10 запросов

2. Запись данных из API в JSON File

Пример

import json
import requests  # требуется установка: pip install requests

response = requests.get("https://api.github.com/users/octocat")
if response.status_code == 200:
    user_data = response.json()
    with open("github_user.json", "w", encoding="utf-8") as f:
        json.dump(user_data, f, ensure_ascii=False, indent=2)
    print("Данные сохранены")
else:
    print("Ошибка запроса")
Файл github_user.json содержит структурированный JSON ответа GitHub API.

3. Запись большого файла построчно (экономия памяти)

Пример

import random

# Генерация 10 млн чисел и запись в файл по частям
with open("big_file.txt", "w") as f:
    for i in range(10_000_000):
        f.write(f"{random.randint(0, 1000)}\n")
        if i % 1_000_000 == 0:
            print(f"Обработано {i} строк")
Вывод: сообщения о прогрессе, файл big_file.txt размером около 80 МБ.

4. Запись в CSV с помощью DictWriter

Пример

import csv

fieldnames = ["name", "age", "city"]
rows = [
    {"name": "Анна", "age": 25, "city": "Москва"},
    {"name": "Иван", "age": 30, "city": "Санкт-Петербург"},
    {"name": "Мария", "age": 28, "city": "Казань"}
]

with open("dict_people.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=fieldnames, delimiter=";")
    writer.writeheader()
    writer.writerows(rows)
Содержимое dict_people.csv:
name;age;city
Анна;25;Москва
Иван;30;Санкт-Петербург
Мария;28;Казань

5. Сериализация объекта с пользовательским методом представления

Пример

import json
from datetime import datetime

class Event:
    def __init__(self, name, date):
        self.name = name
        self.date = date
    
    def to_dict(self):
        return {"name": self.name, "date": self.date.isoformat()}

event = Event("Конференция", datetime(2025, 6, 15))

with open("event.json", "w", encoding="utf-8") as f:
    json.dump(event.to_dict(), f, ensure_ascii=False, indent=2)
Файл event.json:
{
  "name": "Конференция",
  "date": "2025-06-15T00:00:00"
}

6. Запись данных с обработкой ошибок (try-except)

Пример

import os

data = "Важные данные"
filename = "/var/log/app/data.txt"

try:
    os.makedirs(os.path.dirname(filename), exist_ok=True)
    with open(filename, "w", encoding="utf-8") as f:
        f.write(data)
    print("Данные успешно сохранены")
except PermissionError:
    print("Ошибка: недостаточно прав для записи по указанному пути")
except FileNotFoundError:
    print("Ошибка: неверный путь к файлу")
except Exception as e:
    print(f"Неожиданная ошибка: {e}")
Вывод: сообщение об успехе или соответствующий текст ошибки.

7. Запись в бинарный файл (изображения, байты)

Пример

import requests

url = "https://www.python.org/static/community_logos/python-logo-master-v3-TM.png"
response = requests.get(url, stream=True)

with open("python_logo.png", "wb") as f:
    for chunk in response.iter_content(chunk_size=1024):
        f.write(chunk)
Файл python_logo.png скачан и сохранён в текущую директорию.

Сохранение данных в файл - comments

En
Python сохранить (python)