ruamel.yaml克隆节点:保留合并操作符与避免自动锚点
用ruamel.yaml克隆YAML节点并保留合并操作符、避免自动锚点
问题场景
原始YAML结构如下:
main: &base key1: test key2: test dev: <<: *base key3: test
需求是克隆dev节点,深度复制所有属性(包括合并操作符<<:)并将其重命名为stage,期望输出:
main: &base key1: test key2: test dev: <<: *base key3: test stage: <<: *base key3: test
遇到的问题
- 使用
copy.deepcopy克隆时,合并操作符<<:会被异常展开,无法保留原结构 - 参考方案解决合并操作符问题后,当
dev存在嵌套层级(如dev.key4),生成的YAML会自动为嵌套节点创建锚点和别名,不符合需求
解决方案
通过递归函数手动复制节点结构,同时保留合并操作符属性,避免自动生成锚点:
import sys import ruamel.yaml yaml_str = """\ main: &base key1: test key2: test dev: <<: *base key3: test key4: subkey1: test """ def create_copied_stanza(node): copied = ruamel.yaml.comments.CommentedMap() for k, v in node.items(): if k in node._ok: if isinstance(v, ruamel.yaml.comments.CommentedMap): copied[k] = create_copied_stanza(v) else: copied[k] = v return copied def main(): yaml = ruamel.yaml.YAML(typ='rt') original_yaml = yaml.load(yaml_str) dev_node = original_yaml['dev'] # 递归复制节点结构 copied_stage = create_copied_stanza(dev_node) # 手动复制合并操作符属性 copied_stage._yaml_merge = dev_node._yaml_merge original_yaml['stage'] = copied_stage yaml.dump(original_yaml, sys.stdout) if __name__ == "__main__": main()
代码说明
create_copied_stanza函数递归遍历节点,对每个嵌套的CommentedMap也进行深度复制,避免使用deepcopy导致的合并操作符展开问题- 手动复制
_yaml_merge属性,确保合并操作符<<:被保留 - 使用
typ='rt'模式加载YAML,保留原始的注释和结构信息
内容的提问来源于stack exchange,提问作者Andrea Gallina
相关产品推荐
相关产品推荐

