【问题标题】:Is this a valid YAML file?这是一个有效的 YAML 文件吗?
【发布时间】:2020-05-29 14:56:58
【问题描述】:

考虑以下文件:

- k0: v0
  vars: &splat0
    VAR0: potato  # vars from blob0

- k1: v1
  vars: &splat1
    VAR1: spud    # vars from blob1

- k: v
  extra:          # merged vars from blob0 + blob1
    <<: *splat0
    <<: *splat1

它利用了 YAML 的 merge key 特性。

这是一个有效的 YAML 文件吗?规范 (1.1, 1.2) 说,在映射节点中存在“每个键都是唯一的限制”,但是不清楚合并键本身是否是主题到唯一性约束,或者是否只有解析合并后的映射键需要唯一。

PyYAML 对此进行解析并合并键,但 cmets 丢失了。 ruamel 能够保留 cmets 但会引发 DuplicateKeyError,如果您明确允许重复键,则它会解析但合并会丢失。

这个输入是否是有效的 YAML?它应该如何在 Python 中正确解析?

【问题讨论】:

  • “PyYAML 解析这个并合并键,但是 cmets 丢失了”所以它有效吗?我不确定您要做什么,但我不确定问题是否包含它
  • 理想情况下,我想保留 cmets 而不是弄乱合并(我无法控制输入)。但这不是这个问题的目的,这个问题的范围要小得多:YAML 规范中实际上允许重复的合并键
  • 这能回答你的问题吗? Configuring ruamel.yaml to allow duplicate keys
  • 在建议的副本中回答是否正确合并并保留 cmets。
  • 我确定。这个问题是关于 YAML 规范是否允许重复的合并键。该问题的答案并没有解决这个问题(他们实际上是 ruamel 的作者,所以无论如何这都是利益冲突)。但无论如何,这篇文章很有趣,所以谢谢你的链接。

标签: python parsing yaml pyyaml ruamel.yaml


【解决方案1】:

合并键就像任何其他键一样,它们仅以特殊定义的方式进行解释,当 YAML 解析器实现合并键扩展时(这不是必须的)。在我看来,这是无效的 YAML。

但是即使合并键非常特殊以至于它不遵循正常的键限制,也有另一个反对这一点的论点。假设您的输入文件如下所示:

- k0: v0
  vars: &splat0
    VAR0: potato  # vars from blob0
    VAR2: tater

- k1: v1
  vars: &splat1
    VAR1: spud    # vars from blob1
    VAR2: tuber

- k: v
  extra:          # merged vars from blob0 + blob1
    <<: *splat0
    <<: *splat1

还假设您可以将这个不正确的 YAML 加载到 data 中。 data[2]['extra']['VAR2'] 的价值是什么

由于 YAML 规范明确指出:

特别是,在组合过程中不应引用映射键顺序、cmets 和标记句柄。

因此,除非您打破另一个明确的限制(键顺序),否则您无法正确解析它(这是 PyYAML 所做的。恕我直言,这是一个错误)。

这意味着当您正确实现 YAML 规范时,您无法决定是先用VAR2: tuber 还是用VAR2: tater 更新data[2]['extra'] 的值。这就是ruamel.yaml 不允许这样做的原因。

在合并键规范中当然很好地定义了键VAR2的值 当你这样做时,你会得到:

      <<: [*splat0, *splat1]

【讨论】:

  • 嗨,Anthon,我对备用示例不感兴趣,因为在解析合并后,键 VAR2 是非唯一的。因此,无论如何,它都不应该成功解析。我们同意 PyYAML 在这里被窃听,并且他们一直以来都有一个悬而未决的问题......
  • 是什么让您认为VAR2 必须是独一无二的。合并规范明确提到了Keys in mapping nodes earlier in the sequence override keys specified in later mapping nodes.(IIRC PyYAML 对有效的[*splat0, *splat1] 情况也有错误)。
  • 因为在检查欺骗之前解析映射键更有意义,否则您无法检测到相等键上的冲突,例如0xf15 .
  • 看起来 PyYAML 正确地将 [ *BIG, *LEFT, *SMALL ] 合并为 the example,即最终映射以 'r': 10 结束。您还有其他故障模式吗?
  • 我不知道,但是如果您要问我的意见,我认为 YAML 已经太复杂了,我根本不喜欢合并语法.顺便说一句,它似乎也是一个 ruamel.yaml 错误检测重复键,例如最后一个例子:dpaste.com/1MGYMFJ
猜你喜欢
  • 2012-01-06
  • 2014-03-25
  • 2016-11-24
  • 2010-11-25
  • 1970-01-01
  • 2019-07-01
  • 2017-09-30
  • 2011-02-18
  • 1970-01-01
相关资源
最近更新 更多