您可以使用人工编写的YAML进行以下操作:

foo: &foo_anchor
  key1: v1
  key2: v2
  key3: v3
bar:
  <<: *foo_anchor
  key2: override_value


我想以编程方式使用PyYAML生成输出。似乎很棘手!据我所知,默认情况下,PyYAML仅在遇到相等的对象时才生成锚/引用(并且顺序可能未定义,而在此示例中,bar必须引用foo,而不是相反) )。我已经尝试了一些方法-定义YamlReference类并在覆盖的Dumper.serialize_node方法中检查其标记-但尝试执行以下操作:

        if node.tag.endswith('magic.prefix.YamlReference'):
            alias = node.value[0].value
            self.emit(yaml.events.AliasEvent(alias))
            super(Dumper, self).anchor_node(node.value[1])
            super(Dumper, self).serialize_node(node.value[1], parent, idx)


弄乱了预期的事件流。这可能吗?

最佳答案

好吧,你可以做这样的事情:

import yaml

class Merger(object):
  pass

def merger_representer(dumper, data):
  return dumper.represent_scalar(u'tag:yaml.org,2002:merge', '<<')

yaml.add_representer(Merger, merger_representer)

foo = {'key1': 'v1', 'key2': 'v2', 'key3': 'v3'}

root = {
  'foo': foo,
  'bar': {
     Merger(): foo,
     'key2': 'override_value'
  }
}

print(yaml.dump(root, sort_keys=False))


输出为:

foo: &id001
  key1: v1
  key2: v2
  key3: v3
bar:
  <<: *id001
  key2: override_value


sort_keys=False确保键的正确顺序,它要求Python> = 3.7和PyYAML> = 5.1(感谢@tinita)。您无法控制生成的锚名称,但是此YAML等效于您的名称。

您需要Merger类来强制PyYAML发出<<(使用普通的字符串键,它将发出'<<',以免与合并键混淆)。

关于python - 使用pyyaml生成具有覆盖的yaml anchor /引用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59307826/

10-11 20:58