繁体   English   中英

使用 ruamel.yaml 加载 YAML 时复制别名以分隔 Python 对象

[英]Copy aliases to separate Python objects when loading YAML with ruamel.yaml

When loading YAML data using ruamel.yaml, anchors and their aliases in the YAML file are the same object in Python:

from ruamel.yaml import YAML

yaml_str = """\
first: &reference [1, 2, 3]
second: *reference
"""

yaml = YAML()
data = yaml.load(yaml_str)

assert(data['first'] is data['second'])
# passes

data['first'].append(4)
print(data['second'])
# output: [1, 2, 3, 4]

我意识到这是一个有意的功能。 但是,有没有办法告诉load在找到别名时改为复制别名? this answer中所述,我尝试覆盖yaml.representer.ignore_aliases ,但这仅用于写入 YAML,而不是从中读取。

没有内置功能可以做你想做的事。 任何时候遇到别名时,都必须在作曲家中递归地创建一个节点结构,而不是仅仅返回别名的锚节点。

YAML 文档中对锚点和别名的需求源于需要能够表示递归数据结构:

a = [1, 2]
a.append(a)

无法使用您链接到的答案中显示的技术转储上述结构,也不能将表示形式作为 YAML 文档而不进行扩展:

&id001
- 1
- 2
- *id001

在加载期间使用第一段中建议的技术进行扩展。

您的(非递归)示例可以使用链接答案中的技术转储,也可以在加载时进行扩展。

除非您想深入了解 ruamel.yaml,否则最简单的解决方案是加载您的 YAML 文档,扩展转储,然后加载转储结果:

import sys
import ruamel.yaml

yaml_str = """\
first: &reference [1, 2, 3]
second: *reference
"""

yaml = ruamel.yaml.YAML()
yaml.representer.ignore_aliases = lambda *data: True
data = yaml.load(yaml_str)
buf = ruamel.yaml.compat.BytesIO()
out = yaml.dump(data, buf)
data = yaml.load(buf.getvalue())


assert(data['first'] is not data['second'])
assert(data['first'] == data['second'])

data['first'].append(4)
assert len(data['first']) == 4
assert len(data['second']) == 3

当然,当您有一个巨大的文件时,这不是很有效。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM