Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 泡菜的替代品';s'persistent_id`?_Python_Json_Persistence_Yaml_Pickle - Fatal编程技术网

Python 泡菜的替代品';s'persistent_id`?

Python 泡菜的替代品';s'persistent_id`?,python,json,persistence,yaml,pickle,Python,Json,Persistence,Yaml,Pickle,我一直在使用Python的 用于实现基于精简文件的持久性层的模块。这个 持久层(大型库的一部分)严重依赖pickle的特性 将指定类的对象保存为单独的文件 这种方法的唯一问题是pickle文件不是人 可编辑,我更希望将对象保存为 可通过文本编辑器(如YAML或JSON)进行人类可读和编辑 你知道有哪个库使用人工编辑格式和 提供类似于pickle的持久化\u id?或者, 您是否有在YAML-or基础上实施它们的建议 基于JSON的序列化库,无需重写 泡菜?我自己还没有试过,但我认为你应该能够优雅

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

这种方法的唯一问题是pickle文件不是人 可编辑,我更希望将对象保存为 可通过文本编辑器(如YAML或JSON)进行人类可读和编辑

你知道有哪个库使用人工编辑格式和 提供类似于pickle的
持久化\u id
?或者, 您是否有在YAML-or基础上实施它们的建议 基于JSON的序列化库,无需重写
泡菜?

我自己还没有试过,但我认为你应该能够优雅地使用他们所说的东西

编辑

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

重要提示:如果一个
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\u dump
而不是
yaml.dump
。但是不要在
persistable\u representer
persistable\u构造函数中使用它!无需特殊加载功能,只需使用
yaml.load


唷,这花了不少功夫。。。我希望这有帮助

如果没有对持久性系统的目的或要求的任何描述,就很难对如何实现持久性系统提出建议。@taleinat这个问题的范围比实现持久性系统的范围要窄:是否有任何库提供类似于pickle的
persistent\u id
机制的功能,但使用的是人类可编辑的格式?(但你是对的,最后一部分可能会引起一些混乱-我会尝试重写它)非常感谢你的建议!然而,我无法做到这一点(至少不容易做到):主要问题:(1)PyYAML仅基于对象的主类决定使用哪个representer,因此添加属性
persistent\u id
或使对象子类成为指定的
persistent
类是行不通的;(2) 因此,representer函数无法决定是使用“交叉引用”表示法还是普通YAML表示法:这将需要告知何时作为转储另一个对象的一部分调用representer,或者“本机地”调用representer,否则我们将得到无限递归。您的代码正在输入无限递归,因为您正在调用
YAML.dump(data)
在representer中,您告诉
yaml.dump
使用该representer转储数据!尝试在我链接到的PyYAML文档页面中构建representer/constructor示例。具体来说,你应该在你的representer中使用
dumper.representation\u scalar
而不是
yaml.dump
,在你的构造函数中使用
loader.construct\u scalar
而不是
yaml.load
。是的,我知道它为什么会进入无限递归。关键是我不能使用
表示标量
/
构造标量
函数,因为“持久化”对象不是简单的标量,它们是Python对象,我必须获得“常规”YAML表示。这就是pickle的
persistent_id
所做的:它生成正常的pickle表示,但将其保存到另一个文件中。我明白了,您想再次
yaml.dump
对象,但不进行特殊处理,并将其保存到一个文件中,对吗?如果是这样的话,对
pickle做同样的事情会不会有同样的问题?您是如何在基于pickle的解决方案中克服此问题的?是的,正确。在基于泡菜的解决方案中,我没有做任何特殊的魔法;这是泡菜的一个特点,有文献记载。