Python修改YAML值时保留锚点(Anchor)的实现方法
如何修改YAML锚点对应值并保留锚点(ruamel.yaml)
问题场景
我有一个带锚点和别名的YAML文件,内容如下:
dev: value1: &dev-value1 "value1" value2: &dev-value2 "value2" test: value1: *dev-value1 value2: *dev-value2
想要修改dev/value1的值,同时保留其锚点&dev-value1,让test/value1的别名依然指向修改后的值。但用普通赋值的脚本执行后,锚点丢失,生成的文件不符合预期。
原脚本
import ruamel.yaml yaml = ruamel.yaml.YAML() with open("test.eyaml") as eyaml_file: data = yaml.load(eyaml_file) data["dev"]["value1"] = "new_value" with open("new.eyaml", "w") as new_eyaml_file: yaml.dump(data, new_eyaml_file)
错误输出
脚本执行后,锚点跑到了test/value1上,dev/value1的锚点丢失:
dev: value1: new_value value2: &dev-value2 value2 test: value1: &dev-value1 value1 value2: *dev-value2
期望输出
希望修改后锚点仍保留在dev/value1,且别名正确指向新值:
dev: value1: &dev-value1 "new_value" value2: &dev-value2 "value2" test: value1: *dev-value1 value2: *dev-value2
解决方案
ruamel.yaml加载YAML后,锚点对应的是节点对象,直接赋值会替换节点,破坏锚点关联。需要直接修改原节点的value属性,同时保留锚点信息:
修改后的脚本
import ruamel.yaml from ruamel.yaml.scalarstring import DoubleQuotedScalarString yaml = ruamel.yaml.YAML() # 设置和原文件一致的缩进格式 yaml.indent(mapping=4, sequence=4, offset=2) with open("test.eyaml") as eyaml_file: data = yaml.load(eyaml_file) # 获取dev/value1对应的节点对象,直接修改其值 dev_value1_node = data["dev"]["value1"] # 用DoubleQuotedScalarString确保新值带双引号,和原格式匹配 dev_value1_node.value = DoubleQuotedScalarString("new_value") with open("new.eyaml", "w") as new_eyaml_file: yaml.dump(data, new_eyaml_file)
说明
- 保留锚点:直接操作原节点的
value属性,不会破坏节点上绑定的锚点信息,锚点&dev-value1会保留在dev/value1位置。 - 格式匹配:通过
yaml.indent()设置和原文件一致的缩进参数,保证输出格式和原文件对齐。 - 引号控制:使用
DoubleQuotedScalarString包裹新值,确保输出带双引号,和原格式一致;如果需要单引号,可改用SingleQuotedScalarString。
内容的提问来源于stack exchange,提问作者bugZ
相关产品推荐
相关产品推荐

