腌制对象版本控制
Posted
技术标签:
【中文标题】腌制对象版本控制【英文标题】:Pickled Object Versioning 【发布时间】:2011-01-22 14:23:42 【问题描述】:我正在处理一个项目,我们有大量对象被序列化并使用pickle
/cPickle
存储到磁盘。
随着项目生命周期的推进(在向现场客户发布后),未来的功能/修复可能会要求我们更改一些持久对象的签名。这可能是添加字段、删除字段,甚至只是更改一条数据的不变量。
是否有标准的方法来标记将被腌制为具有特定版本的对象(如 Java 中的serialVersionUID
)?基本上,如果我正在恢复 Foo 版本 234 的实例,但当前代码是 236,我希望收到一些关于 unpickle 的通知。我是否应该继续推出自己的解决方案(可能是 PITA)。
谢谢
【问题讨论】:
【参考方案1】:pickle
格式没有这样的附带条件。你为什么不把“序列号”作为对象属性的一部分,和其他的一起腌制呢?然后可以通过比较实际版本和所需版本来轻松获得“通知”——不明白为什么它应该是 PITA。
【讨论】:
是的,这就是我认为我们将要采取的方向。我想我可能高估了添加和检查这些数据所需的工作量。由于我们在一个地方恢复了所有保存的状态,因此添加我们需要的任何逻辑(处理未版本化的对象或以前未版本化但现在的对象应该不会太糟糕)。尽管我会 ping 社区以查看 pickle 是否提供了这种行为并且我正在重新发明***。【参考方案2】:考虑以下由 Tomasz Früboes here 建议的类 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
【讨论】:
效果很好,谢谢!您的链接 (Tomasz Früboes) 已损坏。 我编辑了链接以指向该网站的存档(历史)版本。以上是关于腌制对象版本控制的主要内容,如果未能解决你的问题,请参考以下文章
pickle.dump(模型,pickle_out)| TypeError:无法腌制 _thread._local 对象