使用 ruamel.yaml 加载 YAML 时复制别名以分隔 Python 对象
Copy aliases to separate Python objects when loading YAML with ruamel.yaml
使用 ruamel.yaml 加载 YAML 数据时,YAML 文件中的锚点及其别名是 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
在找到别名时改为 copy 别名?我尝试覆盖 yaml.representer.ignore_aliases
,如 中所述,但这仅用于写入 YAML,而不是从中读取。
没有内置功能可以满足您的需求。任何时候遇到
一个别名,你将不得不在 composer 中递归地创建一个节点结构,而不是仅仅返回别名的锚节点。
YAML 文档中需要锚点和别名是因为需要能够
表示递归数据结构:
a = [1, 2]
a.append(a)
上述结构无法使用您 link 的答案中显示的技术转储,也无法在不扩展的情况下表示为 YAML 文档:
&id001
- 1
- 2
- *id001
使用第一段中建议的技术在加载过程中展开。
您的(非递归)示例可以使用 linked 答案中的技术转储,
并且还可以边加载边展开
最简单的解决方案,除非您想深入了解 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
当然,当你有一个大文件时,这不是很有效。
使用 ruamel.yaml 加载 YAML 数据时,YAML 文件中的锚点及其别名是 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
在找到别名时改为 copy 别名?我尝试覆盖 yaml.representer.ignore_aliases
,如
没有内置功能可以满足您的需求。任何时候遇到 一个别名,你将不得不在 composer 中递归地创建一个节点结构,而不是仅仅返回别名的锚节点。
YAML 文档中需要锚点和别名是因为需要能够 表示递归数据结构:
a = [1, 2]
a.append(a)
上述结构无法使用您 link 的答案中显示的技术转储,也无法在不扩展的情况下表示为 YAML 文档:
&id001
- 1
- 2
- *id001
使用第一段中建议的技术在加载过程中展开。
您的(非递归)示例可以使用 linked 答案中的技术转储, 并且还可以边加载边展开
最简单的解决方案,除非您想深入了解 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
当然,当你有一个大文件时,这不是很有效。