You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()

代码说明

  1. create_copied_stanza函数递归遍历节点,对每个嵌套的CommentedMap也进行深度复制,避免使用deepcopy导致的合并操作符展开问题
  2. 手动复制_yaml_merge属性,确保合并操作符<<:被保留
  3. 使用typ='rt'模式加载YAML,保留原始的注释和结构信息

内容的提问来源于stack exchange,提问作者Andrea Gallina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 00:22:26