# Сохранение и сериализация данных с помощью стандартной библиотеки Python: `json`, `pickle`, `csv` Для сохранения данных в файл или передачи по сети необходима **сериализация**. Python предоставляет три стандартных инструмента, каждый из которых обладает своими особенностями: * **`json`** – человеко‑читаемый текстовый формат, отлично подходит для обмена между языками; * **`pickle`** – бинарный формат, сохраняющий объекты Python «как есть», но с риском безопасности; * **`csv`** – простейший текстовый формат для табличных данных, широко поддерживаемый. ![Форматы доставки данных](/media/editor_temp/6/82b2d285-16b0-473a-b88a-cd9a6f6582f2.png) * **`json`**: человеко‑читаемый, кросс‑язычный; * **`pickle`**: бинарный, сохраняет объекты Python полностью, но опасен; * **`csv`**: простейший текстовый формат для таблиц, универсален. В этой статье мы разберёмся, как выбирать между этими модулями в зависимости от того, **какие данные и для чего** вы хотите сохранить. --- ## 1. JSON {#sec-c0452ee3f8b9} ### 1.1 Общая информация {#sec-573894aef250} JSON (JavaScript Object Notation) – **текстовый** и **языко‑независимый** формат. Он широко используется для конфигурационных файлов, API‑ответов, логов и т.д. В Python работа с JSON осуществляется через модуль `json`. ### 1.2 Основные API (часто используемые) {#sec-7388e1478aff} * `json.dump(obj, fp, ...)` / `json.load(fp, ...)` – сохранение/чтение из файла; * `json.dumps(obj, ...)` / `json.loads(s, ...)` – преобразование в строку/обратное. Полезные параметры: * `ensure_ascii=False` – сохраняет и выводит символы вне ASCII без экранирования; * `indent=2` – форматированный вывод; * `default=...` – функция‑замена для типов, которые не сериализуются по умолчанию. ### 1.3 Пример использования (базовый) {#sec-57d0c0653337} ```python import json data = { "name": "Alice", "age": 30, "skills": ["Python", "Data Science"] } with open("data.json", "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2) with open("data.json", "r", encoding="utf-8") as f: loaded = json.load(f) print(loaded) ``` ### 1.4 Как обойти ограничения типов в JSON {#sec-a43d0fe8a199} JSON поддерживает только `dict`, `list`, `str`, `int/float`, `bool`, `None`. Для таких типов, как `datetime`, необходимо использовать параметр `default`. ```python import json from datetime import datetime, timezone payload = {"created_at": datetime.now(timezone.utc)} def to_jsonable(obj): if isinstance(obj, datetime): return obj.isoformat() raise TypeError(f"Not JSON serializable: {type(obj)!r}") s = json.dumps(payload, default=to_jsonable, ensure_ascii=False) print(s) ``` ### 1.5 Плюсы и минусы {#sec-667d6fad184b} **Плюсы** * Кросс‑язычный обмен; * Читаемость и совместимость с Git; * При загрузке не происходит выполнения кода. **Минусы** * Ограниченная выразительность типов (datetime, set, Decimal, бинарные данные); * При больших данных может быть медленнее и занимать больше места. --- ## 2. Pickle {#sec-7417b1955ccc} ### 2.1 Общая информация {#sec-1889607ea8cb} `pickle` – формат, сохраняющий объекты Python «как есть» в бинарном виде. При загрузке восстанавливается практически идентичный объект. **Когда удобно** * Сохранять сложные объекты Python (классы, вложенные структуры, обученные модели); * Не требуется обмен с другими языками. **Когда не стоит** * При работе с ненадёжными источниками (pickle.load() может выполнить произвольный код); * При необходимости обеспечения совместимости с другими системами. --- ### 2.2 Основные API (4 наиболее часто используемых) {#sec-a0a97fe87a25} * `pickle.dump(obj, file, protocol=...)` – объект → файл; * `pickle.load(file)` – файл → объект; * `pickle.dumps(obj, protocol=...)` – объект → bytes; * `pickle.loads(data)` – bytes → объект. ```python import pickle data = {"a": [1, 2, 3], "b": ("x", "y")} with open("data.pkl", "wb") as f: pickle.dump(data, f) with open("data.pkl", "rb") as f: loaded = pickle.load(f) print(loaded) ``` --- ### 2.3 Что такое `protocol` и зачем его указывать? {#sec-1f8e5565848c} `protocol` – версия формата pickle. Выбор влияет на размер, скорость и совместимость. * По умолчанию используется «наилучший» для текущей версии Python; * Если нужна совместимость с более старыми версиями – укажите более низкий протокол; * Для оптимизации размера/скорости используйте `pickle.HIGHEST_PROTOCOL`. ```python import pickle with open("data.pkl", "wb") as f: pickle.dump({"x": 1}, f, protocol=pickle.HIGHEST_PROTOCOL) ``` --- ### 2.4 Важные предостережения {#sec-007b70a5e9ec} `pickle.load()` может выполнить код, содержащийся в pickle‑файле. Поэтому: * Не загружайте pickle из ненадёжного источника; * Для обмена данных используйте текстовые форматы, например `json`. --- ### 2.5 Плюсы и минусы {#sec-bbd5a24bec31} **Плюсы** * Сохраняет практически любой объект Python; * Быстрее и компактнее, чем `json` для сложных структур. **Минусы** * Риск безопасности – загрузка из ненадёжного источника опасна; * Не совместим с другими языками; * При изменении классов старые pickle‑файлы могут перестать работать. --- ## 3. CSV {#sec-99e590b24e50} ### 3.1 Общая информация {#sec-1265cc44a461} CSV (Comma-Separated Values) – самый простой формат для табличных данных. Часто используется для табличных данных, экспорта/импорта данных и простых логов. ### 3.2 Основные API (часто используемые) {#sec-5b2e4c37cce5} * `csv.reader`, `csv.writer` – работа со списками; * `csv.DictReader`, `csv.DictWriter` – работа с словарями (обычно предпочтительнее). ### 3.3 Пример использования (DictWriter/DictReader) {#sec-524921270351} ```python import csv data = [ {"name": "Alice", "age": 30, "city": "Seoul"}, {"name": "Bob", "age": 25, "city": "Busan"}, ] with open("people.csv", "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=["name", "age", "city"]) writer.writeheader() writer.writerows(data) with open("people.csv", "r", encoding="utf-8") as f: reader = csv.DictReader(f) loaded = list(reader) print(loaded) ``` ### 3.4 Три важные нюанса при работе с CSV {#sec-3db1b7ed8444} 1. **`newline=""` обязателен** – особенно в Windows, чтобы избежать двойных переводов строк; 2. **Все данные считываются как строки** – необходимо вручную преобразовывать типы; 3. **Разделители, кавычки, переводы строк могут встречаться в данных** – используйте модуль `csv`, а не простое `split(',')`. ### 3.5 Плюсы и минусы {#sec-6a8ca4891a8e} **Плюсы** * Очень легкий и универсальный формат; * Поддерживается большинством инструментов. **Минусы** * Сложные вложенные структуры трудно представить; * Отсутствие типовой информации, требуется ручная конвертация. --- ## 4. Сравнение и руководство по выбору {#sec-6304ec188cc0} | Параметр | JSON | Pickle | CSV | | -------- | ----- | ------- | --- | | Совместимость | Очень хорошая | Только Python | Очень хорошая | | Читаемость | Высокая | Низкая (бинарный) | Высокая | | Выразительность типов | Ограниченная | Очень высокая | Ограниченная | | Безопасность | Относительно безопасен | **Внимание** | Относительно безопасен | | Структура данных | Дерево (вложенные) | «Python‑объект как есть» | Таблица (строки/столбцы) | Кратко: * **Обмен с другими системами** → `json`; * **Сохранение Python‑объектов целиком** → `pickle` (с осторожностью); * **Экспорт/импорт таблиц** → `csv`. --- ## 5. Сохранение и восстановление одних данных тремя способами {#sec-21f8c2a6d6c9} ```python import json, pickle, csv data = [ {"id": 1, "name": "Alice", "score": 95.5}, {"id": 2, "name": "Bob", "score": 88.0}, ] # 1) JSON with open("data.json", "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2) with open("data.json", "r", encoding="utf-8") as f: json_loaded = json.load(f) # 2) Pickle with open("data.pkl", "wb") as f: pickle.dump(data, f) with open("data.pkl", "rb") as f: pickle_loaded = pickle.load(f) # 3) CSV with open("data.csv", "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=["id", "name", "score"]) writer.writeheader() writer.writerows(data) with open("data.csv", "r", encoding="utf-8") as f: reader = csv.DictReader(f) csv_loaded = [ {"id": int(row["id"]), "name": row["name"], "score": float(row["score"])} for row in reader ] print(json_loaded) print(pickle_loaded) print(csv_loaded) ``` **Ключевые моменты** * В CSV необходимо вручную преобразовывать типы; * Pickle удобен, но требует осторожности с источником данных. --- ## 6. Итоги {#sec-f88db3766ed6} Стандартная библиотека Python охватывает широкий спектр задач по сохранению и сериализации данных. * **Если данные должны быть читаемыми и совместимыми с другими языками** – используйте `json`; * **Если нужно сохранить объекты Python целиком** – применяйте `pickle` (с учётом безопасности); * **Если требуется простое табличное представление** – выбирайте `csv`. Выбор зависит от формы данных и цели их использования, что делает процесс быстрым и надёжным.