2

我想使用 pickle,特别是 cPickle 将我的对象数据序列化为代表模块、项目、模块对象、场景对象等的文件文件夹。有没有简单的方法可以做到这一点?

因此 unpickling 会有点棘手,因为每个父对象在运行时都存储对子/兄弟对象的引用,但父对象的 pickle 数据将保存对象的文件路径。

我从所有类都继承的 PathUtil 类开始,但一直遇到问题。有没有人解决过数据文件保存/恢复的类似问题/功能?

它与现有代码的工作越透明越好。例如,如果使用元类__call__将使现有的构造函数语法保持不变,那将是一个加分项。例如,静态__call__将首先检查泡菜文件,如果存在则加载它,如果不存在则执行默认构造。

4

1 回答 1

1

您可以覆盖__getstate__以写入新的 pickle 文件并返回其路径,并__setstate__取消文件。

import pickle, os

DIRNAME = 'path/to/my/pickles/'

class AutoPickleable:

    def __getstate__(self):
        state = dict(self.__dict__)
        path = os.path.join(DIRNAME, str(id(self)))
        with open(path, 'wb') as f:
            pickle.dump(state, f)
        return path

    def __setstate__(self, path):
        with open(path, 'b') as f:
            state = pickle.load(f)
        self.__dict__.update(state)

现在,每种应该具有这种特殊的自动腌制行为的类型都应该子类化AutoPickleable.

当您想转储文件时,您可以执行pickle.dumps(obj)copy.deepcopy(obj)忽略结果。

Unpickling 照常工作 ( pickle.load)。如果您想从文件路径(而不是从 的结果pickle.dumps)恢复对象,这有点棘手。如果您需要,请告诉我,我会添加详细信息。无论如何,如果你AutoPickleable用“标准”对象包装你的对象,并对其进行所有泡菜操作,它应该都可以工作。

这种方法有几个潜在的问题,但对于你描述的“干净”的情况,它可能会起作用。

一些注意事项:

  • 无法“动态”指定要写入的目录。它必须是全局可访问的,并且在酸洗操作之前设置
  • 如果多个对象保持对同一个对象的引用,或者您有循环引用,则可能不起作用AutoPickleable(通常,pickle 可以毫无问题地处理这些情况)
  • 这里没有代码来清理目录/删除文件。
于 2017-04-14T08:59:36.687 回答