pickle的“持久性”替代品?

2024-04-29 10:11:13 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直在使用Python的pickle 用于实现基于瘦文件的持久性层的模块。这个 持久层(更大库的一部分)严重依赖pickle的persistent_id特性 将指定类的对象另存为单独的文件。

这种方法的唯一问题是pickle文件不是人类的 可编辑,我更希望对象以 使用文本编辑器(例如,YAML或JSON)可供人类阅读和编辑。

你知道有哪个库使用人类可编辑格式 提供类似于picklepersistent_id的功能?或者, 你有没有建议在YAML-or上实现它们 基于JSON的序列化库,无需重写 泡菜?


Tags: 模块文件对象方法idjson编辑yaml
1条回答
网友
1楼 · 发布于 2024-04-29 10:11:13

我自己还没有尝试过,但我认为你应该可以用PyYAML使用他们所称的"representers" and "resolvers"优雅地完成这项工作。在

编辑

在与海报进行了大量的评论交流之后,下面是一个使用PyYAML实现所需行为的方法。在

重要注意事项:如果一个Persistable实例有另一个这样的实例作为属性,或者以某种方式包含在它的某个属性中,那么所包含的Persistable实例将不会保存到另一个单独的文件中,而是与父实例Persistable实例一起内联保存在同一个文件中。据我所知,这个限制也存在于OP的pickle-based系统中,并且对于他/她的用例来说是可以接受的。我还没有找到一个不涉及黑客攻击的优雅解决方案。在

import yaml
from functools import partial

class Persistable(object):
    # simulate a unique id
    _unique = 0

    def __init__(self, *args, **kw):
        Persistable._unique += 1
        self.persistent_id = ("%s.%d" %
                              (self.__class__.__name__, Persistable._unique))

def persistable_representer(dumper, data):
    id = data.persistent_id
    print "Writing to file: %s" % id
    outfile = open(id, 'w')
    outfile.write(yaml.dump(data))
    outfile.close()
    return dumper.represent_scalar(u'!xref', u'%s' % id)

class PersistingDumper(yaml.Dumper):
    pass

PersistingDumper.add_representer(Persistable, persistable_representer)
my_yaml_dump = partial(yaml.dump, Dumper=PersistingDumper)

def persistable_constructor(loader, node):
    xref = loader.construct_scalar(node)
    print "Reading from file: %s" % id
    infile = open(xref, 'r')
    value = yaml.load(infile.read())
    infile.close()
    return value

yaml.add_constructor(u'!xref', persistable_constructor)


# example use, also serves as a test
class Foo(Persistable):
    def __init__(self):
        self.one = 1
        Persistable.__init__(self)

class Bar(Persistable):
    def __init__(self, foo):
        self.foo = foo
        Persistable.__init__(self)

foo = Foo()
bar = Bar(foo)
print "=== foo ==="
dumped_foo = my_yaml_dump(foo)
print dumped_foo
print yaml.load(dumped_foo)
print yaml.load(dumped_foo).one

print "=== bar ==="
dumped_bar = my_yaml_dump(bar)
print dumped_bar
print yaml.load(dumped_bar)
print yaml.load(dumped_bar).foo
print yaml.load(dumped_bar).foo.one

baz = Bar(Persistable())
print "=== baz ==="
dumped_baz = my_yaml_dump(baz)
print dumped_baz
print yaml.load(dumped_baz)

从现在起,当您想将Persistable类的实例保存到单独的文件中时,请使用my_yaml_dump,而不是{}。但是不要在persistable_representerpersistable_constructor内部使用它!不需要特殊的加载函数,只需使用yaml.load。在

哎呀,这花了点功夫。。。我希望这有帮助!在

相关问题 更多 >