В Python для сериализации (преобразования объектов в последовательность байтов или строку для хранения/передачи) используются модули pickle и json:
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 или расхождение структуры
История
В крупном проекте для хранения пользовательских профилей применялся pickle. После обновления версии Python и изменения классов структура сериализованных объектов потеряла совместимость, что привело к отказу системы и потере большинства данных пользователей.
В веб-сервисе pickle применялся для сессий пользователей. Недоброжелатель загрузил вредоносный pickled-объект, что позволило выполнить инъекцию кода на сервере.
Попытка сериализовать функции через pickle для их передачи по сети завершилась неудачей в ряде сред: pickled-лямбда нельзя перенести между машинами с разными конфигурациями/версиями Python.