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

时间:2018-08-22 16:26:32

标签: python formatting yaml ruamel.yaml

我正在尝试格式化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)

1 个答案:

答案 0 :(得分:0)

您应该升级到最新的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