Как сохранить словарь в файл на Python: обзор методов и примеры кода
Сохранение словарей в файлы: основные подходы
Использование модуля json (рекомендуемый способ)
Как сохранить словарь в читаемом формате, который легко загрузить обратно и использовать в других языках?
Модуль json позволяет сериализовать словарь в текст, удобный для чтения человеком. Этот метод подходит, если словарь содержит только базовые типы (строки, числа, списки, словари, булевы значения, None).
import json
data = {"name": "Анна", "age": 30, "city": "Москва", "skills": ["Python", "SQL"]}
with open("data.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=4)
ввод программ на python (ввод данных в программе python)
Параметр ensure_ascii=False сохраняет кириллицу без экранирования, indent=4 добавляет отступы для читаемости.
Проблема: Если в словаре есть объекты вроде datetime, возникнет ошибка TypeError: Object of type datetime is not JSON serializable.
Решение: Использовать параметр default в json.dump() для преобразования сложных типов, например:
def json_serial(obj):
if isinstance(obj, datetime):
return obj.isoformat()
raise TypeError(f"Type {type(obj)} not serializable")
json.dump(data, f, default=json_serial)
Python file io (ввод-вывод файлов в python)
1. Сохранение с помощью pickle (для любых объектов Python)
Как сохранить словарь, содержащий произвольные объекты (например, функции, классы, сеты)?
Модуль pickle сериализует практически любой объект Python в бинарный формат. Недостаток - файлы не читаются человеком и могут быть несовместимы между версиями Python.
import pickle
data = {"numbers": {1, 2, 3}, "func": lambda x: x*2} # set и лямбда
with open("data.pkl", "wb") as f:
pickle.dump(data, f)
Python temp files (временные файлы в python)
Проблема: При загрузке pickle-файла может возникнуть ошибка UnpicklingError, если файл повреждён или создан другой версией Python.
Решение: Всегда проверять версию pickle (protocol), использовать pickle.HIGHEST_PROTOCOL и обрабатывать исключения.
2. Запись через repr() и eval() (простейший / быстрый способ)
Как быстро сохранить словарь без внешних модулей, имея в виду только безопасное окружение?
Метод подходит для отладки или простых скриптов, где словарь гарантированно состоит из типов, представимых литералами (int, str, list, dict, tuple). Нельзя использовать для пользовательских данных из соображений безопасности (eval).
with open("data.txt", "w", encoding="utf-8") as f:
f.write(repr(data))
Python index files (индексация файлов в python)
Загрузка:
with open("data.txt", "r") as f:
restored = eval(f.read())
File python class (класс для работы с файлами в python)
Проблема: eval() может выполнить произвольный код. Никогда не используйте этот способ, если файл мог быть изменён злоумышленником.
3. Сохранение в CSV (для плоских словарей)
Как сохранить словарь с одноуровневыми ключами и простыми значениями в табличный формат?
Модуль csv подходит, если словарь имеет плоскую структуру (ключи - строки, значения - строки или числа). Каждая строка - одна запись.
import csv
data = {"name": "Иван", "age": 25, "city": "СПб"}
with open("data.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=data.keys())
writer.writeheader()
writer.writerow(data)
Python file utf 8 (кодировка utf-8 для файлов в python)
Проблема: Вложенные словари или списки не могут быть сохранены напрямую. Придётся предварительно преобразовывать.
4. Использование YAML (гибкий формат с поддержкой комментариев)
Как сохранить словарь с произвольной структурой в формате, удобном для конфигурационных файлов?
YAML - человекочитаемый формат, поддерживающий многие типы данных. Необходимо установить библиотеку pyyaml.
import yaml
data = {"server": {"host": "localhost", "port": 8080}, "debug": True}
with open("config.yaml", "w", encoding="utf-8") as f:
yaml.dump(data, f, default_flow_style=False, allow_unicode=True)
Python config files (конфигурационные файлы в python)
Проблема: Некорректное отображение сложных объектов (например, кортежей - в YAML они превращаются в списки).
5. Модуль shelve (словарь, сохраняемый на диск)
Как получить постоянное хранилище с доступом как к обычному словарю?
shelve использует dbm и pickle под капотом. Позволяет записывать и читать объекты по ключу, не загружая весь словарь в память.
import shelve
data = {"key1": [1,2,3], "key2": {"sub": "value"}}
with shelve.open("mydata.shelve") as db:
for k, v in data.items():
db[k] = v
Проблема: Ключи должны быть строками. Не все типы значений поддерживаются (ограничения pickle).
Расширенные примеры сохранения словарей
Пример 1. Сохранение словаря с датами и множествами через json с кастомным сериализатором
import json
from datetime import datetime, date
from decimal import Decimal
def custom_serializer(obj):
if isinstance(obj, (datetime, date)):
return obj.isoformat()
if isinstance(obj, Decimal):
return float(obj)
if isinstance(obj, set):
return list(obj)
raise TypeError(f"Невозможно сериализовать {type(obj)}")
data = {
"timestamp": datetime.now(),
"price": Decimal("19.99"),
"tags": {"python", "json", "example"}
}
with open("advanced.json", "w", encoding="utf-8") as f:
json.dump(data, f, default=custom_serializer, indent=2, ensure_ascii=False)
# Проверка содержимого
with open("advanced.json", "r", encoding="utf-8") as f:
print(f.read())
{
"timestamp": "2025-04-14T12:34:56.789012",
"price": 19.99,
"tags": ["python", "json", "example"]
}
Пример 2. Сохранение большого словаря по частям (генератор)
import json
def chunked_dict(items, chunk_size=1000):
"""Генератор, возвращающий фрагменты словаря."""
partial = {}
for idx, (k, v) in enumerate(items):
partial[k] = v
if (idx + 1) % chunk_size == 0:
yield partial
partial = {}
if partial:
yield partial
big_dict = {f"key_{i}": i for i in range(5000)}
with open("big_dict.json", "w", encoding="utf-8") as f:
f.write("[")
first = True
for chunk in chunked_dict(big_dict.items()):
if not first:
f.write(",\n")
json.dump(chunk, f, ensure_ascii=False, indent=2)
first = False
f.write("]")
# Результат - JSON массив из нескольких объектов
Пример 3. Сохранение в формат msgpack (бинарный компактный формат)
# pip install msgpack
import msgpack
data = {"key": [1, 2, 3], "nested": {"a": "test"}}
with open("data.msgpack", "wb") as f:
packed = msgpack.packb(data, use_bin_type=True)
f.write(packed)
# Чтение
with open("data.msgpack", "rb") as f:
loaded = msgpack.unpackb(f.read(), raw=False)
print(loaded)
{'key': [1, 2, 3], 'nested': {'a': 'test'}}
Пример 4. Сохранение с использованием h5py (для научных данных)
# pip install h5py
import h5py
import numpy as np
data = {
"metadata": "experiment",
"values": np.array([1.5, 2.3, 4.1]),
"sub": {"nested_int": 42}
}
with h5py.File("data.hdf5", "w") as f:
f.attrs.update(data["metadata"]) # атрибуты для метаданных
f.create_dataset("values", data=data["values"])
grp = f.create_group("sub")
grp.attrs["nested_int"] = data["sub"]["nested_int"]
Пример 5. Сохранение словаря с ключами-числами (json требует строки)
import json
data = {1: "one", 2: "two", 3: "three"}
# JSON допускает только строковые ключи, поэтому преобразуем
with open("numeric_keys.json", "w") as f:
# Используем ключи как строки, а при загрузке преобразуем обратно
json.dump({str(k): v for k, v in data.items()}, f)
# Загрузка с обратным преобразованием
with open("numeric_keys.json", "r") as f:
loaded = json.load(f)
restored = {int(k): v for k, v in loaded.items()}
print(restored)
{1: 'one', 2: 'two', 3: 'three'}
Пример 6. Асинхронное сохранение с помощью aiofiles (для асинхронных приложений)
import aiofiles
import json
import asyncio
data = {"async": True, "value": 100}
async def save_dict_async():
async with aiofiles.open("async_data.json", "w", encoding="utf-8") as f:
await f.write(json.dumps(data, indent=2, ensure_ascii=False))
asyncio.run(save_dict_async())