ПрограммированиеBackend разработчик

Поясните, как работает встроенный механизм сериализации данных в Python (модули pickle и json). Чем они отличаются, для чего используются, какие опасности таит неосмотрительная сериализация?

Проходите собеседования с ИИ помощником Hintsage

Ответ

В Python для сериализации (преобразования объектов в последовательность байтов или строку для хранения/передачи) используются модули pickle и json:

  • pickle сериализует любые объекты Python (даже классы и функции!), но результат — бинарная последовательность. Работает только внутри экосистемы Python.
  • json сериализует только простые структуры данных (dict, list, str, int, float), зато результатом будет строка (универсальный формат), совместимая с другими языками.

Pickle использовать для хранения/пересылки данных между неподконтрольными сторонами опасно, т.к. при десериализации можно выполнить произвольный вредоносный код. json этим недостатком не обладает.

Пример работы:

import pickle import json # Pickle (бинарная сериализация) data = {'x': 10, 'func': lambda x: x + 1} with open('data.pkl', 'wb') as f: pickle.dump(data, f) # JSON (только простые объекты) data = {'x': 10, 'y': [1, 2, 3]} with open('data.json', 'w') as f: json.dump(data, f)

Вопрос с подвохом

Вопрос: Можно ли использовать pickle для сериализации и сохранения любых объектов Python между сессиями? Почему этот механизм не рекомендуется для сохранения пользовательских данных?

Ответ:

Нет, использовать pickle повсеместно — плохая практика. Помимо безопасности (при загрузке "чужого" pickled-объекта выполнение может быть компрометировано), есть проблема несоответствия версий Python или классов — сериализованные объекты могут не загрузиться или повести себя некорректно, если структура классов изменилась.

Пример:

# Загрузка pickle-файла, структура класса поменялась import pickle with open('old_version.pkl', 'rb') as f: obj = pickle.load(f) # AttributeError или расхождение структуры

История

Пример 1

В крупном проекте для хранения пользовательских профилей применялся pickle. После обновления версии Python и изменения классов структура сериализованных объектов потеряла совместимость, что привело к отказу системы и потере большинства данных пользователей.


Пример 2

В веб-сервисе pickle применялся для сессий пользователей. Недоброжелатель загрузил вредоносный pickled-объект, что позволило выполнить инъекцию кода на сервере.


Пример 3

Попытка сериализовать функции через pickle для их передачи по сети завершилась неудачей в ряде сред: pickled-лямбда нельзя перенести между машинами с разными конфигурациями/версиями Python.