Модуль pickle
реализует двоичные протоколы для сериализации и десериализации структуры объекта Python. "Pickling" - это процесс, посредством которого иерархия объектов Python преобразуется в поток байтов, а "unpickling" - обратная операция, посредством которой поток байтов, из двоичного файла или объекта, подобного байту преобразуется обратно в иерархию объектов.
Чтобы сериализовать иерархию объектов, вы просто вызываете функцию pickle.dumps()
. Аналогично, для десериализации потока данных вы вызываете функцию pickle.loads()
. Если нужно больше контроля за упаковкой и особенно распаковкой данных, то можно создать объект pickle.Pickler()
или pickle.Unpickler()
соответственно.
Для справки: функции, названия которых оканчиваются на символ 's'
(damps, loads) - работают со строками.
Предупреждение!
pickle
не защищен. Распаковывайте данные только те, которым вы доверяете. Можно сериализовать данные, которые будут выполнять произвольный код во время распаковки. Никогда не извлекайте данные, которые могли прийти из ненадежного источника или могли быть подделаны.hmac
для того, чтобы быть уверенным, что они не были подделаны.В Python есть более примитивный модуль сериализации, называемый marshal
. Этот модуль существует главным образом для поддержки файлов Python .pyc
и ввиду его не частого применения не будет рассматривается на этом сайте. В общем случае pickle
всегда должен быть предпочтительным способом сериализации объектов Python.
Существуют фундаментальные различия между протоколами Pickle
и JSON
:
JSON
- это текстовый формат сериализации, а pickle
- это двоичный формат сериализации;JSON
читается человеком, а pickle
- нет;JSON
широко используется за пределами экосистемы Python, в то время как Pickle
зависит от Python;По умолчанию JSON
может представлять только подмножество встроенных типов Python, а не пользовательские классы. Pickle
может представлять чрезвычайно большое количество типов Python. Сложные случаи могут быть решены путем реализации определенных объектных API.
В отличие от pickle
, десериализация ненадежного JSON
сама по себе не создает уязвимости при выполнении произвольного кода.
Формат данных, используемый модулем pickle
зависит от Python. Это имеет то преимущество, что нет никаких ограничений, налагаемых внешними стандартами, такими как JSON
или XDR
, которые не могут представлять совместное использование указателей. Это означает, что программы, не являющиеся Python, могут не иметь возможности реконструировать выбранные объекты Python.
По умолчанию формат данных pickle
использует относительно компактное двоичное представление. Если вам нужны оптимальные характеристики размера, вы можете эффективно сжимать упакованные данные.
В настоящее время существует 6 различных протоколов, которые можно использовать для сериализации. Чем выше используется протокол, более поздние версии Python требуется, что бы прочитать сериализованные данные.
Примечание.
Сериализация - более примитивное понятие, чем постоянство. Хотя pickle
читает и записывает файловые объекты, он не решает проблему именования постоянных объектов, а также, даже более сложную проблему одновременного доступа к постоянным объектам. Модуль pickle
может преобразовать сложный объект в поток байтов и может преобразовать поток байтов в объект с такой же внутренней структурой. Возможно, наиболее очевидная вещь, которую нужно сделать с этими потоками байтов - это записать их в файл, но также возможно отправить их по сети или сохранить их в базе данных. Модуль shelve
предоставляет простой интерфейс для выбора и удаления объектов в файлах базы данных в стиле DBM
.
Простейший код использования dump()
и load()
функцию.
>>> import pickle # используемый протокол по умолчанию >>> pickle.DEFAULT_PROTOCOL # 3 # создадим данные для записи >>> data1 = {'a': [1, 2.0, 3, 4+6j], ... 'b': ('string', u'Unicode string'), ... 'c': None} >>> selfref_list = [1, 2, 3] >>> selfref_list.append(selfref_list) # открываем файл для записи >>> output = open('data.pkl', 'wb') >>> pickle.dump(data1, output) # список запишем по протоколу 4 >>> pickle.dump(selfref_list, output, 4) # закрываем файл >>> output.close()
В следующем примере считываются упакованные данные.
>>> import pprint, pickle >>> pkl_file = open('data.pkl', 'rb') >>> data1 = pickle.load(pkl_file) >>> pprint.pprint(data1, width=60) # {'a': [1, 2.0, 3, (4+6j)], # 'b': ('string', 'Unicode string'), # 'c': None} >>> data = pickle.load(pkl_file) >>> pprint.pprint(data2, width=60) # [1, 2, 3, <Recursion on list with id=139710613355592>] >>> pkl_file.close()