包含自定义标签的 YAML 文件中的 pyYAML 加载行?

pyYAML load line in YAML file containing custom Tag?

我有第三方工具使用的以下 YAML 文件。

timezone: "Europe/Zurich"

_export:
  py:
    python: ${virtualenv_home}/bin/python3
  log_level: INFO
  poll_interval: 1
  workflow_name: test_workflow

!include : 'params.yml'

+say_hello:
  echo>: Hello world!

我的目标是使用 PyYAML 加载此 YAML 文件并更改一些内容,然后将其转储到文件中。 如果“!include:'params.yml'”不是这样的话,这会很好用。

我将如何加载这一行,以便如果它被转储到文件中,它看起来与现在一样“!include:'params.yml'? 实际包含将由第三方工具处理。

我尝试了以下 post 的答案,但没有得到正确的结果。

? !include ''
: params.yml

谢谢

从某种意义上说,您得到的结果是正确的,与您的输入是等价的。

PyYAML 和一般的 YAML 不是一种您可以完全控制数据序列化方式的格式。在某些情况下,它只会做出您无法影响的决定。让我们用一个最小的例子来检查一下:

import yaml, sys
node = yaml.compose("!include : 'params.yml'")
yaml.serialize(node, sys.stdout)

此代码仅将输入加载到节点级别,其中保留了有关键和值样式的信息。然后它再次将其转储为 YAML。输出是

? !include ''
: 'params.yml'

如您所见,即使 PyYAML 知道 !include '' 最初是一个隐式键,其内容是一个空的纯标量,它仍然将其序列化为显式键它的内容是一个空的单引号标量。从 YAML 的角度来看,这等同于原始输入,只是使用了不同的 YAML 样式。

这个实验表明你不能强制PyYAML以你想要的风格输出键值对,因为即使它知道原来的风格,它仍然会改变它。这意味着除非您修改 PyYAML 本身,否则无法实现您想要的。

如果您可以控制 YAML 文件的最终使用者,我建议更改结构如下:

$include: 'params.yml'

在您的原始文件中使用 !include 已经违背了规范的意图,因为标签应该应用于它们所标记的值。但是,在您的情况下, !include 标记了一个空标量,该标量是一个映射键,但似乎已应用于该键的值。如果你想拥有一个对其值做一些特殊事情的键,你应该让键成为一个具有特殊值的标量,而不是一个带有特殊标签的空标量。通过使用 $include,在保留 YAML 样式的同时进行修改要容易得多。 IIRC OpenAPI 使用与 $ref.

类似的技术