【问题标题】:How to load a pickle object and resolve certain references如何加载泡菜对象并解析某些引用
【发布时间】:2016-05-04 11:40:05
【问题描述】:

假设我们有一个使用pickle 写入二进制文件的对象。假设对象图如下所示:

foo1
 +--->bar
 |     \--->context
 +--->baz
 |     +--->context
 |     \--->qux
 \--->context

现在context 对象是大型数据结构,qux 的所有实例都是相同的。因此,我们决定将这些 contexxt 对象排除在泡菜过程之外:

def __getstate__(self):
    my_dict = dict(self.__dict__)
    my_dict['context'] = None  # We don't save the context
    return my_dict

对于 foobarbaz 所属的类(实际上是我们设计中的所有其他类)。

当我们将load() 对象放回内存时,我们希望将所有context 引用设置回给定的上下文。可以通过递归遍历对象树来做到这一点,但我们想知道pickle 中是否有更优雅的解决方案,可以在将数据加载回内存时自行填充context 值?

【问题讨论】:

  • 您是在寻找__setstate__ 还是我错过了什么?
  • @IljaEverilä:问题是__setstate__ 没有额外的参数,因此我们可以设置上下文。尽管如此,我想我已经在 persistent pickling (docs.python.org/3.2/library/pickle.html#pickle-persistent) 中找到了答案。
  • 很好,不知道(参考外部对象支持)。您自己的发现似乎是可行的方法。

标签: python pickle


【解决方案1】:

如果.context 的类型为Context,您可以修改pickle 文档中Persistence of External Objects 部分的代码,而不是将context 设置为None

import pickle

class ContextAwarePickler(pickle.Pickler):
    def persistent_id(self, obj):
        # if this is a context, return the key
        if isinstance(obj, Context):
            return ("Context", context.key)

        # pickle as usual
        return None


class ContextAwareUnpickler(pickle.Unpickler):
    def recover_context(self, key_id):
        ...

    def persistent_load(self, pid):
        type_tag, key_id = pid
        if type_tag == "Context":
            return self.recover_context(key_id)
        else:
            raise pickle.UnpicklingError("unsupported persistent object")

【讨论】:

  • 谢谢。问这个问题几分钟后,我找到了这个例子。尽管如此,修改后的代码更容易理解。 +1。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多