如何在不定义构造函数的情况下保留标签的同时进行往返yaml

How to do round trip yaml while preserving tags without defining constructors

我试图在不修改注释、锚点和标签的情况下格式化 YAML 代码(基本上采用任意 YAML 代码并强制执行特定缩进和其他格式约定)。为此,我使用具有往返功能的 ruamel.yaml 0.15.0(几乎是这个示例逐字 https://yaml.readthedocs.io/en/latest/example.html)。

一切都按预期工作,但转储功能正在尝试解析标签。我似乎无法找到任何关于如何在保留标签而不是尝试加载标签的同时实际转储的信息。我宁愿不必为这些标签定义构造函数。任何人都知道有什么方法可以做到这一点?

这是一个简单的例子:

import sys
import ruamel.yaml

yaml_str = """\
- &predef
  b: 42
- !sometag
  a: "with superfluous quotes"   # and with comment
  b: *predef
  c: |
     literal
     block style
     scalar
"""

yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)

yaml_str2 = """\
# example
name: &hey
  # details
  family: !the_tag Smith   # very common
  given: Alice    # one of the siblings
name2: *hey
"""
data2 = yaml.load(yaml_str2)
yaml.dump(data2, sys.stdout)

奇怪的是第一个示例有效而第二个示例无效!是什么赋予了?这是我收到的错误:

- &predef
  b: 42
- !!sometag
  a: "with superfluous quotes"   # and with comment
  b: *predef
  c: |
    literal
    block style
    scalar
Traceback (most recent call last):
  File "format_yaml.py", line 31, in <module>
    data2 = yaml.load(yaml_str2)
  File "/opt/bb/lib/python2.7/site-packages/ruamel/yaml/main.py", line 252, in load
    return constructor.get_single_data()
  File "/opt/bb/lib/python2.7/site-packages/ruamel/yaml/constructor.py", line 102, in get_single_data
    return self.construct_document(node)
  File "/opt/bb/lib/python2.7/site-packages/ruamel/yaml/constructor.py", line 112, in construct_document
    for dummy in generator:
  File "/opt/bb/lib/python2.7/site-packages/ruamel/yaml/constructor.py", line 1279, in construct_yaml_map
    self.construct_mapping(node, data)
  File "/opt/bb/lib/python2.7/site-packages/ruamel/yaml/constructor.py", line 1187, in construct_mapping
    value = self.construct_object(value_node, deep=deep)
  File "/opt/bb/lib/python2.7/site-packages/ruamel/yaml/constructor.py", line 162, in construct_object
    data = next(generator)  # type: ignore
  File "/opt/bb/lib/python2.7/site-packages/ruamel/yaml/constructor.py", line 1359, in construct_undefined
    node.start_mark)
ruamel.yaml.constructor.ConstructorError: could not determine a constructor for the tag '!the_tag'
  in "<byte string>", line 4, column 11:
      family: !the_tag Smith   # very common
              ^ (line: 4)

您应该升级到最新的 0.15.X 版本,并检查您是否 使用 YAML() 的正确实例化(没有 typ='safe', 然后使用其 .load().dump() 方法:

import sys
import ruamel.yaml


yaml_str = """\
# example
name: &hey
  # details
  family: !the_tag Smith   # very common
  given: Alice    # one of the siblings
name2: *hey
"""


yaml = ruamel.yaml.YAML()
# yaml.indent(mapping=4, sequence=4, offset=2)
yaml.preserve_quotes = True
data = yaml.load(yaml_str)
data['name']['given'] = 'Bob'
yaml.dump(data, sys.stdout)

给出:

# example
name: &hey
  # details
  family: !the_tag Smith   # very common
  given: Bob      # one of the siblings
name2: *hey