首页 > 解决方案 > 解析 ruamel.yaml 中的多个自定义标签

问题描述

背景:在我的计算机视觉程序中,用户正在修改 YAML 文件以提供注释功能(列表项是函数,标量序列是参数)。工作流程是open/modify YAML file > save yaml > parse and execute functions > show results, and start over or save. 在一个文件中可以有同一工具的多个实例,通过“id”标量进行区分。由于注释在每次迭代后都会保存,因此还需要控制覆盖行为,这也是用标量控制的。

- create_annotation: 
  id: my_id1
  overwrite: false
  tool: mask
- create_annotation: 
  id: my_id2
  overwrite: true
  tool: mask

问题我想开始使用一些自定义 YAML 标签来将实例/覆盖语句与函数参数分开(看起来更直观)。我使用ruamel.yaml并查看了类似的问题,其中标签通过类“注册”,然后添加到构造函数中。但是,我不确定加载后是否要检索标签信息(它不在ordereddict/CommentedMap 中)。

问题

  1. 如何从节点构建和加载自定义标签,在哪里可以找到它?
  2. 每个节点可以有多个标签吗?

预期结果

我希望有这样的事情:

- create_annotation: !id my_id1 !ow false 
  tool: mask
- create_annotation: !id my_id2 !ow true 
  tool: mask

这将被解析为:

{tool: mask,
 id: my_id1,
 overwrite: false}

标签: pythonyamlruamel.yaml

解决方案


从第二个问题开始:不,每个节点不能有多个标签。节点属性在YAML 文档中指定

[96]    c-ns-properties(n,c) ::=   ( c-ns-tag-property
                                     ( s-separate(n,c) c-ns-anchor-property )? )
                                 | ( c-ns-anchor-property
                                     ( s-separate(n,c) c-ns-tag-property )? ) 

这不允许多个标签属性。通常,该标签用于创建特定的类实例,我不确定需要实例化或组合多个此类实例。

所以如果你解析你的例子会发生什么,!id它将被视为标量 string 的标签my_id1 !ow false,它恰好有一些看起来像标签的东西作为字符串的一部分:

import ruamel.yaml

yaml_str = """\
- create_annotation: !id my_id1 !ow false 
  tool: mask
- create_annotation: !id my_id2 !ow true 
  tool: mask
"""

yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
scalar = data[0]['create_annotation']
print(f'scalar: "{scalar}", id: "{scalar.tag.value}"')

这使:

scalar: "my_id1 !ow false", id: "!id"

正如您所看到的,标签是它之前的值节点的一部分,并且不存储CommentedMap它是它的一部分。


推荐阅读