【问题标题】:Incorrect format (No newline chars) when loading YAML with embedded JSON使用嵌入式 JSON 加载 YAML 时格式不正确(无换行符)
【发布时间】:2019-02-22 10:13:52
【问题描述】:

我正在尝试从文件中解析 YAML 输入:

root: {
   children : { key: "test-key", version: "{{ test_version | default( '1.0.0-SNAPSHOT' ) }}"}
}

我正在使用 ruamel.yaml,使加载的代码部分配置为保留引号,然后我手动添加一个新条目:

yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
yaml.width = 4096
yaml.indent(sequence=4, offset=2)

with open(yml_file, 'r') as file:
   print("Modifying file: '%s'..." % str(file))
   data = yaml.load(file)

data['root'][new_project_name.lower()] = {'key': "%s" % new_project_name.lower(),
                                                          'test_version': "{{ %s_version | default(\'1.0.0-SNAPSHOT\') }}"
                                                                     % new_project_name.lower()}

 with open(yml_file, 'w') as file:
       yaml.dump(data, file)

问题是,当使用新条目写入文件时,我将所有内容都放在同一行中,因此似乎没有保留新行(CR LF),(它似乎在没有它们的情况下加载它) 你知道有什么方法可以保存它们吗?

输出是(同一行中的所有内容):

root: {children : { key: "test-key", version: "{{ test_version | default( '1.0.0-SNAPSHOT' ) }}"}}

【问题讨论】:

  • 检查问题stackoverflow.com/questions/24418449/pretty-output-with-pyyaml。答案通过pyyamlruamel.yaml 提供可能的解决方案
  • 你的输出是假的,它不能用我知道的任何版本的ruamel.yaml 生成。代码中没有在映射指示器和键之间生成空格的部分,当然也没有代码有时会这样做(在key: 之前),有时不会(在children: 之前)。 总是提供工作代码,这样我们就可以看到你真正做了什么(错误),只是缺少几行可以剪切和粘贴,为什么要让事情不完整?
  • 你是对的,我需要编辑输出来向你展示这个概念,所以可能我犯了一个错误,遗憾的是我不能使用原始代码。无论如何,正如你说的那样,没有空格,输出是一样的。

标签: python-3.x ruamel.yaml


【解决方案1】:

ruamel.yaml 不保留 cmets 也不保留间距 流内 风格。如果你关心布局,那么你的 YAML 更容易 人类阅读,您应该最大程度地使用流式风格的叶子 如果有的话。这是使用YAML(typ='fast')时的默认转储样式。

当您像输入一样嵌套流样式时,这些节点上的流样式为 保留,并完成标准格式(除了换行,如果行 变得很大,所有东西都在一条线上)。

设置缩进级别只影响块样式结构。

您应该将输入更改为仅叶节点流样式,以获得更好的可读性:

root: 
   children: {key: "test-key", version: "{{ test_version | default( '1.0.0-SNAPSHOT' ) }}"}

这会加载到与您的输入相同的数据结构中。

现在你可以这样做了:

import sys
import ruamel.yaml

yml_file = 'input.yaml'
new_project_name = 'NPN'


yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
yaml.width = 4096

with open(yml_file, 'r') as file:
   print("Modifying file: '%s'..." % str(file))
   data = yaml.load(file)

npn_lower = new_project_name.lower()

data['root'][npn_lower] = m = ruamel.yaml.comments.CommentedMap([
    ('key',  "%s" % npn_lower),
    ('test_version', "{{ %s_version | default(\'1.0.0-SNAPSHOT\') }}" % npn_lower)
])
m.fa.set_flow_style()

with open('output.yaml', 'w') as fp:
    yaml.dump(data, fp)

哪个打印:

Modifying file: '<_io.TextIOWrapper name='input.yaml' mode='r' encoding='UTF-8'>'...

并且有output.yaml:

root:
  children: {key: "test-key", version: "{{ test_version | default( '1.0.0-SNAPSHOT' ) }}"}
  npn: {key: npn, test_version: "{{ npn_version | default('1.0.0-SNAPSHOT') }}"}

注意事项:

  • 添加一个 CommentedMap,就像在普通字典上一样,你不能单独设置 流样式,您需要这样做,因为这不再是嵌套的 流式。元素作为元组列表添加,与 旧版本的 Python 的关键顺序不保证是 与您的输入相同。您还创建了一个空的CommentedMap() 和 一次添加一个键/值对。

  • 在尝试过程中(以及此处提供的代码),它总是 更改输入文件是个坏主意,就像每次测试运行你的 必须恢复输入。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-15
    • 2013-08-24
    • 1970-01-01
    • 2019-02-15
    • 1970-01-01
    相关资源
    最近更新 更多