在 YAML 中作为值列出

List as a value in YAML

我有一个 YAML 模板,它将通过用户输入来填写。要关注的部分是“硬件”,因为值可以是例如[abc, def]abc[abc, def, ghi].

当输入为'abc'时。在 YAML 中,它显示为 abc。但是当值为 '[abc, def]' 时,它显示为带有引号的 '[abc, def]'。我正在寻找一种不包含 quotes.

的方法
TEMPLATE = """
router:
  arrangements:
  - range:
      start: INPUT
      stop: INPUT
    hardware: INPUT
  - range:
      start: INPUT
      stop: INPUT
    hardware: INPUT
"""

yaml = YAML()
config = yaml.load(TEMPLATE)
config['router']['arrangements'][1]['hardware'] = '[def, ghi]'

data_format = ruamel.yaml.comments.CommentedMap(config)

with open('test.yaml', 'w') as _f:
    ruamel.yaml.dump(
        data_format,
        stream=_f,
        Dumper=ruamel.yaml.RoundTripDumper,
        explicit_start=False,
        width=1024
    )

预期输出:

hardware: [def, ghi]

当前输出:

hardware: '[def, ghi]'

如果您使用 round-trip 转储程序,ruamel.yaml 默认情况下会以块样式转储任何添加的字典/列表。 如果你想创建一个流式序列,你必须采取图书馆采取的额外步骤 当 round-tripping flow-style 元素时:

import sys
import ruamel.yaml

TEMPLATE = """
router:
  arrangements:
  - range:
      start: INPUT
      stop: INPUT
    hardware: INPUT
  - range:
      start: INPUT
      stop: INPUT
    hardware: INPUT
"""

def flow_seq(l):
    ret_val = ruamel.yaml.comments.CommentedSeq(l)
    ret_val.fa.set_flow_style()
    return ret_val

yaml = ruamel.yaml.YAML()
yaml.explicit_start = False
yaml.width = 1024

config = yaml.load(TEMPLATE)
config['router']['arrangements'][1]['hardware'] = flow_seq(['def', 'ghi'])

assert isinstance(config, ruamel.yaml.comments.CommentedMap)

yaml.dump(config, sys.stdout)

给出:

router:
  arrangements:
  - range:
      start: INPUT
      stop: INPUT
    hardware: INPUT
  - range:
      start: INPUT
      stop: INPUT
    hardware: [def, ghi]

不需要像您那样使用旧样式ruamel.yaml.dump()进行输出。您可以控制 YAML() 实例 您通过设置其属性用于输入输出。

我还建议通过流式传输到标准输出进行测试,这比查看文件内容容易得多。 一旦一切正常,您可以将最后一行替换为:

 from pathlib import Path
 out_file = Path('test.yaml')

 yaml.dump(config, out_file)

如果用户输入以方括号分隔的字符串 '[def, ghi]' 形式出现,您可以使用类似

的方式进行转换
s = '[def, ghi]'  # replace by the user input
l = [x.strip() for x in s.lstrip('[').rstrip(']').split(',')]