使用 ruamel.yaml 解析 YAML 注释

Parsing YAML comments with ruamel.yaml

我正在尝试使用 ruamel.yaml 解析 yaml 文件的注释。问题是,我想以某种特定的方式(尽管我认为这是逻辑)来解析评论。我有以下 yaml 文件:

---
# comment for the foo variable
foo: 'foo_val'

# comment for the bar variable
bar: ['item1', 'item2']

我一直在努力做的是:

from ruamel.yaml import YAML
yaml = YAML()
yaml.preserve_quotes = True
yaml.explicit_start = True

stream = open('my_file.yml', 'r')
loaded = yaml.load(stream) # by default is roundtrip

loaded.ca 
print(loaded)

什么打印以下内容:

Comment(
start=[None, [CommentToken('# comment for the foo variable\n', line: 1, col: 0)]],
items={
foo: [None, None, CommentToken('\n\n# comment for the bar variable\n', line: 3, col: 0), None]})

ordereddict([('foo', 'foo_val'), ('bar', ['item1', 'item2'])])

如您所见,评论的地图(我相信它是这样命名的)不保持顺序。我试过另一种方法,在变量定义下方进行评论,但使用 Python 样式列表也不起作用。

有谁知道是否可以在不将第一个评论视为 start 对象的情况下获取评论地图?基本上,我的预期输出将是每个变量,评论就在最上面,即:

Comment(
    items={
    foo: [None, None, CommentToken('\n\n# comment for the foo variable\n', line: 0, col: 0), None],
    bar: [None, None, CommentToken('\n\n# comment for the bar variable\n', line: 3, col: 0), None],
  })

编辑

理想情况下,我需要保持我展示的示例中的格式,或者直接从一种格式转换为另一种格式。

YAML 规范要求丢弃注释。因此,它们的指定方式无法让您严格控制它们关联的节点。

ruamel 尽最大努力将评论映射到它认为它们所属的位置,以便可以复制初始输入,但它通常不能在保留 YAML 语法的同时为您提供您所要求的控制。

一个可能的解决方案是使用显式键语法,这样您就可以在键后面写下注释,这将创建一个清晰的关联:

? foo # comment for the foo variable
: 'foo_val'
? bar # comment for the bar variable
: ['item1', 'item2']

经 Anthon 确认目前无效的原始提案:

一个可能的解决方案是使用流映射,它有一个明确的开始,因此注释肯定在映射内部:

{
  # comment for the foo variable
  foo: 'foo_val',

  # comment for the bar variable
  bar: ['item1', 'item2']
}

请注意 'foo_val' 后的逗号,这是流语法所要求的。缩进是可选的。

ruamel.yaml 中的注释原则上与正在处理的集合的 key/index 的节点相关联,因此几乎从来没有与解析器尚未看到的内容相关联(比如你想)。这有一些例外(文件中任何数据之前的注释,键和值之间的注释),但这是一般规则。空行和全行注释被视为行尾注释的延续(即使它们对于某个 key/index 不存在)。

所以虽然你的解释是正确的,但目前还没有简单的方法来获得你想要的评论。改进工作正在进行中(控制“后续”完整行注释和空行的关联方式),但没有估计何时包含。