如何加载泡菜对象并解析某些引用

How to load a pickle object and resolve certain references

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

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

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

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 值本身?

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

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")