Сообщить об ошибке.

Какие данные можно сохранять при помощи pickle

Можно упаковывать следующие типы:

  • None, True и False;
  • Целые числа, числа с плавающей точкой, комплексные числа;
  • Строки, байты, байтовые массивы;
  • Кортежи, списки, множества и словари, содержащие только перечисленные здесь объекты;
  • Функции, определенные на верхнем уровне модуля с помощью ключевого слова def, lambda-функции упаковывать нельзя;
  • Встроенные функции, определенные на верхнем уровне модуля;
  • Классы, которые определены на верхнем уровне модуля.

Попытки упаковать необратимые объекты вызовут исключение PicklingError. Когда это происходит, то в базовый файл уже может быть записано неопределенное количество байтов. Попытка выбрать многорекурсивную структуру данных может превысить максимальную глубину рекурсии, в этом случае будет вызвана ошибка RecursionError. Вы можете осторожно поднять этот предел с помощью sys.setrecursionlimit().

Обратите внимание, что функции (встроенные и определяемые пользователем) выбираются по "полной" ссылке на имя, а не по значению. Это означает, что выбирается только имя функции, а также имя модуля, в котором определена функция. Ни код функции, ни какой-либо из ее атрибутов функции не выбираются. Таким образом определяющий модуль должен быть импортируемым в среде распаковки и модуль должен содержать именованный объект, в противном случае будет сгенерировано исключение.

Точно так же классы выбираются по именованным ссылкам, поэтому применяются те же ограничения в среде удаления. Обратите внимание, что ни код, ни данные класса не упакованы, поэтому в следующем примере атрибута attr класса не восстанавливается в среде распаковки:

class Foo:
    attr = 'A class attribute'

picklestring = pickle.dumps(Foo)

Именно из-за этих ограничений выбираемые функции и классы должны быть определены на верхнем уровне модуля.

Точно так же, когда экземпляры класса подвергаются сериализации, код и данные их класса не обрабатываются вместе с ними. Только данные экземпляра упаковываются. Это сделано специально, поэтому можно исправлять ошибки в классе или добавлять методы к классу и по-прежнему загружать объекты, созданные в более ранней версии класса.