可以在从旧样式转换为新样式后取消类实例吗?

时间:2012-04-05 21:54:17

标签: python inheritance pickle

在python中,是否可以在转换为新式python类后将其作为旧式python类进行pickick? (即具有不同“类签名”的对象)。 *

例如,假设某些实例保存为:

class foo: # old style

然后在将类更改为从对象继承之后再腌制几个对象:

class foo(object): # new style

pickle.dump'对象的对象可以由同一样式类pickle.load编辑,但两者都不会同时加载。我认为pickle使用的策略基于继承而变化(从对象继承的类具有自动定义的__reduce__方法,但没有继承的方法没有)。当试图从没有继承的代码(旧式定义)加载带有继承的旧式pickle时,我得到了与此SO question中看到的相同的参数错误;即使第二个参数是多余的,它仍然会更改“类签名”和预期参数,并阻止加载。为了解决这个问题,我很乐意写一个破坏者,虽然我担心它可能涉及两个单独的分类分类器a la the docs ...如果我知道如何正确地去除每个人,我会没事的这样做。

关于我的情况的一些背景......我正在使用TrialHandler类来保存和重新加载按钮按压和行为心理学实验的反应时间。我们重构了TrialHandler类以从更抽象的baseTrialHandler继承,但是这样做会暂时将类签名更改为继承自 object 。但是,我们无法解开较旧的trial_handler文件,因此将其更改回来。我想查看与两个版本的试用处理程序一起运行的同一实验的数据,因此想要在同一个脚本中取消同类两种类型的已保存日志文件。

或者,如果我不能编写一个可以解开两个对象的自定义unpickler,还有另一种方法来序列化它们吗?我试着直接倾向于yaml,但看起来我必须将这个类注册为可以被yaml'ized的东西,无论如何。

PsychoPy邮件列表中包含特定错误的完整description of the problem。任何博客文章解释细节中间酸洗,甚至python继承,将是最受欢迎的;我找到的最接近的是一个很好的解释,为什么pickling is insecure将酸洗描述为“简单的基于堆栈的虚拟机”,这很好,但是我甚至不能弄明白甚至是拔掉自己的基础知识。 / p>

1 个答案:

答案 0 :(得分:5)

通过部分:

  1. 虽然我没有在Python中称为“类签名”的东西 从你的问题中得到了想法
  2. 不应该继承Python 2程序中的“object” 被认为是错误。不从对象继承的类 - 也是 被称为“旧式”的课程,其中只保留了语言 向后兼容性,当引入新的样式类时 Python 2.2(大约2000/2001年) - 旧式的课程要少得多 一致且缺乏许多功能,使今天的python如此 很好的语言。
  3. 在此过程中:unpickle将尝试根据类限定名称反序列化对象 - 如<module>.<class>中所示,就像在酸洗时对象的__class__.__name__属性中所示。所以有可能有一种天真的方式,在一个unpickle异常(它引发TypeError),交换具有相同名称的可用类,并重试unpickle操作 再说一遍:你的类应该继承自“object”(更具体地说,有一个基于“类型”的元类)

    至于我提到的例子,juust写了一些东西:

    try:
        new_obj = pickle.load(data_stream)
    except TypeError: # if you know this was caused due to the new version of "Foo" class:
        current_foo = foomodule.Foo
        foomodule.Foo = foomodule.OldFoo
        new_obj = pickle.load(data_stream)
        foomodule.Foo = current_foo