如何在不解析锚点值的情况下导出YAML内容?
问题描述
我有如下YAML文件:
anchor1: &anchor1 resource_class: small anchor2: &anchor2 hello: world anchor3: &anchor3 hello: world root1: nested1: <<: *anchor1 some_list: - item1: hello: world - *anchor2 - *anchor3 nested2: <<: *anchor1 some_list: - item1: hello: world - *anchor2 - *anchor3 nested3: <<: *anchor1 some_list: - item1: hello: world - *anchor2 - *anchor3 root2: nested1: <<: *anchor1 some_list: - item1: hello: world2 - *anchor2 - *anchor3 ...
我想要将nested1的值提取到单独文件中,且不解析所有锚点。使用如下代码:
from pathlib import Path from ruamel.yaml import YAML yaml = YAML() with open(Path('in_file')) as f: data = yaml.load(f) with open(Path('out_file'), 'w') as f: yaml.dump(data['root1']['nested1'], f)
期望导出的输出为:
<<: *anchor1 some_list: - item1: hello: world - *anchor2 - *anchor3
我知道这是无效YAML(缺少锚点定义),但核心需求是保留锚点引用而非展开内容。目前遇到的问题是:提取子节点后,锚点已被自动解析合并,导出的是展开后的数据;但如果dump整个文件,锚点引用能正常保留。推测是因为锚点定义不在data['root1']的范围内,但不知道如何解决。
解决方案
问题出在默认加载模式下,ruamel.yaml会自动解析合并锚点内容,丢失原始的引用标记。要保留锚点引用,需要使用round trip模式加载YAML,该模式会完整保留原始的结构、锚点、注释等信息。
修改后的代码如下:
from pathlib import Path from ruamel.yaml import YAML # 使用round trip模式初始化YAML对象 yaml = YAML(typ='rt') yaml.preserve_quotes = True # 可选,保留原始引号格式 with open(Path('in_file')) as f: data = yaml.load(f) # 提取目标节点 target_node = data['root1']['nested1'] with open(Path('out_file'), 'w') as f: yaml.dump(target_node, f)
原理说明
round trip模式(typ='rt')是ruamel.yaml专为保留YAML原始格式设计的模式,它会:
- 保留锚点(
&anchor)和引用(*anchor)的原始结构,不会自动合并展开 - 保留注释、换行、引号等格式细节
- 用特殊的字典类型(如
CommentedMap、MergeKeyDict)存储节点,记录原始的合并操作(<<: *anchor)
这样dump目标子节点时,就能输出期望的锚点引用格式,而不是展开后的内容。
内容的提问来源于stack exchange,提问作者doodla
相关产品推荐
相关产品推荐

