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

如何用ruamel.yaml区分YAML锚点定义与锚点引用?

区分ruamel.yaml中的锚点定义与引用

在ruamel.yaml默认加载逻辑中,锚点引用会被直接解析为原始节点的引用,导致无法通过节点的yaml_anchor()方法区分哪个键对应锚点定义、哪个对应引用。可以根据需求选择以下两种解决方案:

场景1:保留原始结构,不解析引用

如果不需要让引用指向原始节点,仅需区分定义和引用,加载时设置resolve=False,此时引用会以AnchorReference对象形式保留,直接判断类型即可:

import ruamel.yaml
from ruamel.yaml.comments import AnchorReference

yaml_str = """
foo: &some_anchor
  bar: 1

baz: *some_anchor
"""

yaml = ruamel.yaml.YAML()
yaml.resolve = False  # 关键:禁用引用解析,保留原始标记
data = yaml.load(yaml_str)

for key, val in data.items():
    if isinstance(val, AnchorReference):
        print(f"键 {key} 是锚点引用,引用锚点: {val.anchor}")
    else:
        anchor_obj = val.yaml_anchor()
        if anchor_obj and anchor_obj.anchor:
            print(f"键 {key} 是锚点定义,锚点名称: {anchor_obj.anchor}")

运行输出:

键 foo 是锚点定义,锚点名称: some_anchor
键 baz 是锚点引用,引用锚点: some_anchor

场景2:解析引用的同时区分定义与引用

如果需要让引用指向原始节点(即baz的值与foo的值为同一个对象),可以通过遍历YAML事件流,提前记录锚点的定义和引用对应的键:

import ruamel.yaml
from ruamel.yaml.parser import Parser
from ruamel.yaml.scanner import Scanner

yaml_str = """
foo: &some_anchor
  bar: 1

baz: *some_anchor
"""

# 第一步:遍历事件流,记录锚点信息
anchor_def_map = {}  # 锚点名称 -> 对应的定义键
anchor_ref_list = []  # 存储(引用键, 锚点名称)

current_key = None
scanner = Scanner(yaml_str)
parser = Parser(scanner)

for event in parser:
    # 处理带锚点的事件
    if hasattr(event, 'anchor') and event.anchor:
        # 锚点定义事件(对应值为字典的情况)
        if isinstance(event, ruamel.yaml.events.MappingStartEvent):
            anchor_def_map[event.anchor] = current_key
        # 锚点引用事件
        elif isinstance(event, ruamel.yaml.events.ScalarEvent) and event.anchor.startswith('*'):
            anchor_ref_list.append((current_key, event.anchor.lstrip('*')))
    # 记录当前遍历到的键
    elif isinstance(event, ruamel.yaml.events.ScalarEvent) and not event.anchor:
        current_key = event.value

# 第二步:正常加载YAML数据(引用已解析为原始节点)
yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)

# 输出区分结果
print("锚点定义对应键:")
for anchor, key in anchor_def_map.items():
    print(f"  锚点 {anchor} → 键 {key}")

print("\n锚点引用对应键:")
for key, anchor in anchor_ref_list:
    print(f"  键 {key} → 引用锚点 {anchor}")

运行输出:

锚点定义对应键:
  锚点 some_anchor → 键 foo

锚点引用对应键:
  键 baz → 引用锚点 some_anchor

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 20:11:47