我正在开发一个项目,我们使用pickle
/ cPickle
将大量对象序列化并存储到磁盘。
随着项目的生命周期的进展(在向现场客户发布之后),未来的功能/修复可能需要我们更改某些持久对象的签名。这可能是添加字段,删除字段,甚至只是更改一段数据的不变量。
是否有一种标准方法可以将一个被腌制的对象标记为具有某个版本(如Java中的serialVersionUID
)?基本上,如果我正在恢复Foo版本234的实例,但当前代码是236我想收到关于unpickle的一些通知。我应该继续推出自己的解决方案(可能是PITA)。
由于
答案 0 :(得分:4)
pickle
格式没有这样的附带条件。为什么不将“序列版本号”作为对象属性的一部分,与其余属性一起腌制?然后通过比较实际版本和期望版本可以轻而易举地获得“通知” - 不明白为什么它应该是PITA。
答案 1 :(得分:0)
请考虑以下TomaszFrüboeshere建议的类混合。
# versionable.py
class Versionable(object):
def __getstate__(self):
if not hasattr(self, "_class_version"):
raise Exception("Your class must define _class_version class variable")
return dict(_class_version=self._class_version, **self.__dict__)
def __setstate__(self, dict_):
version_present_in_pickle = dict_.pop("_class_version")
if version_present_in_pickle != self._class_version:
raise Exception("Class versions differ: in pickle file: {}, "
"in current class definition: {}"
.format(version_present_in_pickle,
self._class_version))
self.__dict__ = dict_
__getstate__
在酸洗时由pickle
调用,而__setstate__
在酸洗时由pickle调用。此混合类可用作您要跟踪其版本的类的子类。它的用法如下:
# bla.py
from versionable import Versionable
import pickle
class TestVersioning(Versionable):
_class_version = 1
t1 = TestVersioning()
t_pickle_str = pickle.dumps(t1)
class TestVersioning(Versionable):
_class_version = 2
t2 = pickle.loads(t_pickle_str) # Throws exception about wrong class version