2014-09-04 3 views
0

Модуль PPython позволяет регистрировать специальные редукторы и конструкторы. Правильно ли, что я могу настраивать нечеткое поведение объектов, которые я сериализовал после Я зарегистрировал пользовательский сериализатор/несериализатор через copy_reg.pickle?Настроить поведение рассола для обратной совместимости

Пример:

import pickle, copy_reg 

class C(object): 
    pass 

legacy_c_ser = pickle.dumps(C()) 

def reduce_C(obj): 
    print('reduce_C called') 
    tpl = obj.__reduce__() 
    tpl = (load_C,) + tpl[1:] 
    return tpl 

def load_C(*tpl): 
    print('load_C called') 
    return C() 

copy_reg.constructor(load_C) 
copy_reg.pickle(C, reduce_C, load_C) 

new_c_ser = pickle.dumps(C()) 

# load_C is called 
pickle.loads(new_c_ser) 

# load_C is not called 
pickle.loads(legacy_c_ser) 

Кажется, что copy_reg работает, просто заменив функцию конструктора в формате маринада:

>>> print(legacy_c_ser) 
'ccopy_reg\n_reconstructor\np0\n(c__main__\nC\np1\[...]' 
>>> print(new_c_ser) 
'c__main__\nload_C\np0[...]' 

пишет мой собственный pickle.Unpickler класс единственный способ настроить unpickle поведение старых файлов рассола? Я не хочу этого делать, поскольку я предпочитаю использовать cPickle, чем pickle из-за эффективности.

Моя проблема в том, что у меня есть маринованные предметы из сторонней библиотеки, а формат рассола изменился, когда я обновил библиотеку.

ответ

1

Предполагается, что Pickle совместим с обратной связью по версиям python (давайте проигнорируем python 2.x против 3.x, пока). Поэтому, когда вы говорите, что формат травления изменился, вы имеете в виду способ, которым эта библиотека сторонних организаций регистрирует свои классы (или другие объекты), изменилась, правильно?

Если это так ... чтобы сделать эту работу, вам нужно сделать некоторые обманы. Сначала вы получаете исходное значение для определения старого класса, и когда вы захватываете сырой маринад, вам нужно изменить ссылку из существующего класса, чтобы соответствовать пути к коду для старой версии класса. Это должно быть в четком тексте (даже в HIGHEST_PROTOCOL), поэтому не следует пытаться захватить и отредактировать эту часть строки рассола. Затем вы сможете разложить старые объекты, но они будут указывать на определение старого класса. Для преобразования старых объектов, которые вы будете использовать для новых объектов экземпляра класса, необходим конвертер формата. В основном создаются новые экземпляры классов, которые принимают соответствующее состояние из старых экземпляров класса.

+0

> Предполагается, что Pickle совместим с обратной связью по версиям python (давайте проигнорируем python 2.x против 3.x, пока). Поэтому, когда вы говорите, что формат травления изменился, вы имеете в виду способ, которым эта библиотека сторонних организаций регистрирует свои классы (или другие объекты), изменилась, правильно? –

+0

благодарит Майка - звучит очень смело, чтобы изменить маринованную кашу, чтобы изменить зарегистрированного бездельника - есть ли какая-нибудь сторонняя библиотека, которая здесь помогает? –

+1

Это не так плохо, как кажется. Как я уже сказал, название класса должно быть в четком тексте, поэтому вы сможете это сделать. Я написал сериализованную библиотеку под названием 'dill', которая делает подобные вещи, и может отслеживать сериализованные классы и экземпляры классов при изменениях в определении класса ... но не совсем то, что вам нужно, я думаю. У 'dill' могут быть некоторые другие хорошие инструменты для вас, например, возможность захватить исходный код из файла и« сбрасывать »его на диск. https://github.com/uqfoundation –

Смежные вопросы