Модуль pickle

Модуль pickle предоставляет функции и классы для сериализации и десериализации объектов. В программировании под сериализацией понимают преобразование каких-либо данных в набор байтов, который потом обычно сохраняют в файл или передают по сети. Десериализация - это восстановление объектов из их байтовых представлений.

Часто сериализация используется для сохранения пользовательских данных между разными сессиями работы приложения, обычно игры. Более простой пример - вы работаете в интерактивном режиме и создали список или словарь, который захотите использовать в следующий раз. Для этого с помощью функции dump() модуля pickle вы сохраняете объект в файл, а с помощь load() восстанавливаете в следующий раз.

>>> a = [1, 10, 0, -3, 9]
>>> b = {'a': 1, 'b': 2}
>>> import pickle
>>> f = open('data', 'wb')
>>> pickle.dump(a, f)
>>> pickle.dump(b, f)
>>> f.close()
>>> del a
>>> a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> f = open('data', 'rb')
>>> a = pickle.load(f)
>>> a
[1, 10, 0, -3, 9]
>>> c = pickle.load(f)
>>> c
{'a': 1, 'b': 2}
>>> c == b
True
>>> c is b
False

В Python большинство объектов можно сериализовать. Однако не все. Кроме того, следует быть осторожными при сериализации объектов, созданных на основе собственных классов. Сериализуется только объект, но не класс. При десериализации класс импортируется. Поэтому не следует определять классы в том же файле, где будут создаваться и сериализоваться объекты.

Кроме методов dump() и load() есть аналогичные dumps() и loads(), которые работают без файлов. Набор байтов используется в программе.

>>> a = [1, 10, 0, -3, 9]
>>> ab = pickle.dumps(a)
>>> ab
b'\x80\x03]q\x00(K\x01K\nK\x00J\xfd\xff\xff\xffK\te.'
>>> b = pickle.loads(ab)
>>> b
[1, 10, 0, -3, 9]
>>> type(ab)
<class 'bytes'>

Пользоваться pickle лучше только в рамках python-приложения. При обмене данными между разными языками программирования обычно используют модуль json. Также pickle никак не решает вопрос безопасности данных. Поэтому не следует десериализовать данные из неизвестных источников.

Более ранние версии Python могут не понимать протокол сериализации более поздних версий. Для совместимости в функции можно передавать номер протокола.

>>> pickle.DEFAULT_PROTOCOL
3
>>> pickle.HIGHEST_PROTOCOL
4
>>> a = [1, 2, 3]
>>> ab = pickle.dumps(a, 2)
>>> b = pickle.loads(ab)
>>> b
[1, 2, 3]