Pickling - это мини-язык, который можно использовать для преобразования соответствующего состояния из объекта python в строку, где эта строка однозначно представляет объект. Затем (un) травление может быть использовано для преобразования строки в живой объект путем «восстановления» объекта из сохраненного состояния и создания строки.
>>> import pickle
>>>
>>> class Foo(object):
... y = 1
... def __init__(self, x):
... self.x = x
... return
... def bar(self, y):
... return self.x + y
... def baz(self, y):
... Foo.y = y
... return self.bar(y)
...
>>> f = Foo(2)
>>> f.baz(3)
5
>>> f.y
3
>>> pickle.dumps(f)
"ccopy_reg\n_reconstructor\np0\n(c__main__\nFoo\np1\nc__builtin__\nobject\np2\nNtp3\nRp4\n(dp5\nS'x'\np6\nI2\nsb."
Здесь вы можете видеть, что pickle не сохраняет исходный код для класса, но сохраняет ссылку на определение класса. По сути, вы можете почти прочитать выбранную строку… она говорит (грубо переведено) «вызовите реконструктор copy_reg, где аргументы - это класс, определенный __main__.Foo
, а затем выполните другие действия». Другой материал - это сохраненное состояние экземпляра. Если вы посмотрите глубже, вы можете извлечь, что «строка x» установлена в «целое число 2» (примерно: S'x'\np6\nI2
). На самом деле это вырезанная часть маринованной строки для словарной статьи… dict
означает f.__dict__
, что составляет {'x': 2}
. Если вы посмотрите на исходный код pickle
, он очень четко дает перевод для каждого типа объекта и операции с python на маринованный байт-код.
Обратите внимание, что существуют разные варианты языка травления. По умолчанию используется протокол 0, который более понятен человеку. Также есть протокол 2, показанный ниже (и 1,3, и 4, в зависимости от используемой вами версии Python).
>>> pickle.dumps([1,2,3])
'(lp0\nI1\naI2\naI3\na.'
>>>
>>> pickle.dumps([1,2,3], -1)
'\x80\x02]q\x00(K\x01K\x02K\x03e.'
Опять же, это все еще диалект языка травления, и вы можете видеть, что в строке протокола 0 написано «получить список, включите I1, I2, I3», в то время как протокол 2 труднее читать, но говорит то же вещь. Первый бит \x80\x02
указывает, что это протокол 2 - тогда у вас есть ]
, который говорит, что это список, и снова вы можете видеть целые числа 1,2,3 там. Опять же, проверьте исходный код для pickle, чтобы увидеть точное отображение для языка pickle.
Чтобы перевернуть травление в строку, используйте load / load.
>>> p = pickle.dumps([1,2,3])
>>> pickle.loads(p)
[1, 2, 3]