我一直在使用Python的pickle 用于实现基于瘦文件的持久层的模块。该 持久层(较大的库的一部分)在很大程度上依赖于pickle的persistent_id功能 将指定类的对象保存为单独的文件。
这种方法的唯一问题是pickle文件不是人类 可编辑的,我宁愿让对象以一种格式保存 人类可读和可编辑的文本编辑器(例如,YAML或JSON)。
您知道任何使用人工可编辑格式和的库
提供与 pickle persistent_id
类似的功能?或者,
你有建议在YAML-或者YAML之上实施它们吗?
基于JSON的序列化库,无需重写大部分子集
泡菜
答案 0 :(得分:4)
我自己还没有尝试过,但我认为您应该能够使用他们所谓的PyYAML来"representers" and "resolvers"优雅地完成此任务。
修改强>
在与海报广泛交换意见后,这是一种使用PyYAML实现所需行为的方法。
重要说明:如果Persistable
实例具有另一个此类实例作为属性,或以某种方式包含在其中一个属性中,那么包含的Persistable
实例将不会保存到另一个单独的文件,而不是内联保存在与父Persistable
实例相同的文件中。据我所知,这种限制也存在于OP的基于pickle的系统中,并且对于他/她的用例可能是可接受的。我没有找到一个优雅的解决方案,不涉及黑客yaml.representer.BaseRepresenter
。
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)
从现在开始,当您想要将my_yaml_dump
类的实例保存为单独的文件时,请使用yaml.dump
而不是Persistable
。但不在persistable_representer
和persistable_constructor
内使用它!不需要特殊的加载功能,只需使用yaml.load
。