首页 > 解决方案 > 如何使用 | 更新 YML 文件 分隔符

问题描述

我有一个看起来像这样的 .yml 文件。

nlu:
- intent: greet
  examples: |
    - hey
    - hello
    - hi
    - hello there

现在我想更新这个文件以从 python 添加一个新的意图和示例。但由于文件有 | 每当我更新它时,文件的对齐方式就会变得混乱。

像这样

with open('nlu.yml', 'r') as yamlfile:
    cur_yaml = yaml.safe_load(yamlfile)
    cur_yaml['nlu'].append({ 'intent': 'name', 'examples': ['first', 'second']})

with open('nlu.yml', 'w') as yamlfile:
     yaml.safe_dump(cur_yaml, yamlfile)

标签: pythonpython-3.xyamlpyyaml

解决方案


|不是分隔符。它是块标量的标头,意味着 的值examples是与内容的标量"- hey\n- hello\n- hi\n- hello there\n"。要附加具有相同语义结构的另一个序列项,您需要执行

with open('nlu.yml', 'r') as yamlfile:
    cur_yaml = yaml.safe_load(yamlfile)
    cur_yaml['nlu'].append({ 'intent': 'name', 'examples': "- first\n- second\n"})

完整的工作示例:

import yaml, sys

input = """
nlu:
- intent: greet
  examples: |
    - hey
    - hello
    - hi
    - hello there
"""

cur_yaml = yaml.safe_load(input)
cur_yaml['nlu'].append({ 'intent': 'name', 'examples': "- first\n- second"})

yaml.safe_dump(cur_yaml, sys.stdout)

这输出

nlu:
- examples: '- hey

    - hello

    - hi

    - hello there

    '
  intent: greet
- examples: '- first

    - second

    '
  intent: name

现在,虽然此输出具有正确的 YAML 语义,但您可能不喜欢它的格式化方式。有关为什么会发生这种情况的深入解释,请参阅此问题

从那里的答案中得出的结论是,要保留样式,您需要在较低级别修改 YAML 文件的内容,以便 Python 不会忘记原始样式。我已经在这个答案中展示了如何做到这一点。使用那里定义的函数,您可以达到您想要的输出,如下所示:

append_to_yaml("input.yaml", "output.yaml", [
  AppendableEvents(["nlu"],
    [MappingStartEvent(None, None, True), key("intent"), key("name"),
     key("examples"), literal_value("- hello there\n- general Kenobi\n"),
     MappingEndEvent()])])

这会将您的 YAML 输入转换为

nlu:
- intent: greet
  examples: |
    - hey
    - hello
    - hi
    - hello there
- intent: name
  examples: |
    - hello there
    - general Kenobi

推荐阅读