9

我正在做一个项目,我们有大量对象被序列化并使用pickle/存储到磁盘cPickle

随着项目生命周期的推进(在向现场客户发布后),未来的功能/修复可能会要求我们更改一些持久对象的签名。这可能是添加字段、删除字段,甚至只是更改一条数据的不变量。

是否有一种标准方法来标记将被腌制为具有特定版本的对象(如serialVersionUID在 Java 中)?基本上,如果我正在恢复 Foo 版本 234 的实例,但当前代码是 236,我希望收到一些关于 unpickle 的通知。我是否应该继续推出自己的解决方案(可能是 PITA)。

谢谢

4

2 回答 2

6

pickle格式没有这样的附带条件。你为什么不把“序列号”作为对象属性的一部分,和其他的一起腌制呢?然后可以通过比较实际版本和所需版本来轻松获得“通知”——不明白为什么它应该是 PITA。

于 2010-03-02T06:20:23.823 回答
3

考虑 Tomasz Früboes在此处建议的以下类 mixin 。

# 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
于 2018-08-22T14:26:26.180 回答