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

Possible to Unpickle class instances after being converted from old to new style?

在Python中,在转换为新样式的类之后,是否可以取消pickle作为旧样式的Python类的对象?(即具有不同"类签名"的对象)。*

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

1
class foo: # old style

然后在将类更改为从对象继承后,再处理几个对象:

1
class foo(object): # new style

带有一个pickle.dump的对象可以由同一样式类进行pickle.loaded,但两者都不能加载。我认为pickle使用的策略是基于继承而改变的(从对象继承的类有一个自动定义的_uuu reduce_uuu方法,但是没有继承的类没有)。当试图从没有继承的代码(旧样式定义)中加载带有继承的旧样式pickle时,我会得到与这个问题中相同的参数错误;即使第二个参数是多余的,它仍然会更改"类签名"和预期参数,并阻止加载。为了解决这个问题,我很乐意写一个unpickler,尽管我担心它可能涉及两个单独的子类unpickler a la the docs…如果我知道如何正确地拆开每一个,我就可以这样做了。

我的情况有点背景…我正在使用Trialhandler类为行为心理学实验保存和重新加载按钮和反应时间。我们将TrialHandler类重构为从更抽象的BaseTrialHandler继承,但这样做会暂时将类签名更改为从对象继承。但是,我们无法取消拾取旧的试用处理程序文件,因此它被改回。我想看看在两个版本的试用处理程序中运行的同一个实验中的数据,因此想在同一个脚本中取消选取两种类型的已保存日志文件。

或者,如果我不能编写一个自定义的取消拾取器来取消拾取这两个对象,还有其他方法来序列化它们吗?我试着直接把它扔给yaml,但是看起来我必须把这个类注册为可以被yaml化的东西。

有具体错误的问题的完整描述在精神病邮件列表中。任何解释中间酸洗,甚至是python继承细节的博客文章都是最受欢迎的;我发现最贴切的解释就是为什么酸洗是不安全的,把它描述成一个"简单的基于堆栈的虚拟机",这很好,但我还没有足够的时间去弄清楚自己拔的基础。


通过部件:

  • 在python中没有所谓的"类签名",尽管我从你的问题中得到了这个想法
  • 不从python 2程序中的"object"继承应该是认为是错误。不从对象继承的类-也称为"老风格"的课程,在那里只学习语言向后兼容性,当引入新样式类时python 2.2(大约是2000/2001年)-老式类要少得多一致性和缺乏许多特性,使得今天的Python好语言。
  • 这样一来:unpickle将尝试根据类限定名反序列化对象,就像在.中一样,就像在pickle时对象的__class__.__name__属性中那样。因此,可能有一种简单的方法,即在unpickle异常(它引发typeerror)上,用相同的名称交换可用类,然后重试unpickle操作。同样:类应该从"对象"继承(更具体地说,有一个基于"类型"的元类)

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

    1
    2
    3
    4
    5
    6
    7
    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