如何将ruamel.yaml字符串如“ on”往返

时间:2019-03-20 03:22:09

标签: ruamel.yaml

使用ruamel.yaml来回往返某些YAML时,出现以下问题。鉴于此输入:

root:
  matchers:
    - select: "response.body#state"
      test: all
      expected: "on"

我看到以下输出:

root:
  matchers:
    - select: response.body#state
      test: all
      expected: on

请注意,在YAML中,on解析为布尔值true,而off解析为false

以下代码用于读取/写入:

# Use the default (round-trip) settings.
yaml = YAML()

if args.source == '-':
    src = sys.stdin
else:
    src = open(args.source)

doc = yaml.load(src)
process(args.tag, set(args.keep.split(',')), doc)

if args.destination == '-':
    dest = sys.stdout
else:
    dest = open(args.destination, 'w')

yaml.dump(doc, dest)

process函数未修改值。爬网结构后,它只会删除输入中带有特殊标记的内容。

如何使输出为字符串而不是布尔值?

1 个答案:

答案 0 :(得分:1)

您这样写:

  

请注意,在YAML中,on解析为布尔值true,而off解析为false

那句话是不正确的(或者更好: 十年来还不是真的。如果您的on中没有引号 就像您的输出中那样,YAML在使用ruamel.yaml时显然不是这种情况:

import sys
import ruamel.yaml

yaml_str = """\
root:
  matchers:
    - select: response.body#state
      test: all
      expected: on
"""

yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
expected = data['root']['matchers'][0]['expected']
print(type(expected), repr(expected))

给出:

<class 'str'> 'on'

这是因为在YAML 1.2规范中,on / off / yes / no是否 之前提到的含义与true相同 分别false。他们在YAML 1.1规范中提到了 ,但这是 在2009年被取代。不幸的是, 自从那时以来就没有更新过。

实际情况是您的引号过多 输入将被往返过程自动丢弃。您可以 还可以看到值"response.body#state"会发生这种情况。虽然 包含开始注释的字符(#), 实际开始评论必须要处理的角色 空格,并且由于不是空格,所以不需要引号。

所以您的输出很好,但是如果不幸的话 您必须处理依赖于其他程序的情况 YAML 1.1已过时,那么您可以例如指定您要保留 您的往返报价:

yaml_str = """\
root:
  matchers:
    - select: "response.body#state"
      test: all
      expected: "on"
"""

yaml = ruamel.yaml.YAML()
yaml.indent(sequence=4, offset=2)
yaml.preserve_quotes = True
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)

因为这会提供您的准确输入:

root:
  matchers:
    - select: "response.body#state"
      test: all
      expected: "on"

但是,也许更好的选择是您实际指定 YAML通过且现在必须遵守YAML 1.1规范 您的意图以及输出文档 explicit

yaml_str = """\
root:
  matchers:
    - select: response.body#state
      test: all
      expected: on
"""

yaml_in = ruamel.yaml.YAML()
yaml_out = ruamel.yaml.YAML()
yaml_out.indent(sequence=4, offset=2)
yaml_out.version = (1, 1)
data = yaml_in.load(yaml_str)
yaml_out.dump(data, sys.stdout)

请注意,“未加引号的” YAML 1.2输入会给出引号on的输出:

%YAML 1.1
---
root:
  matchers:
    - select: response.body#state
      test: all
      expected: 'on'