【问题标题】:Add multiple docs in yaml file | PyYAML在 yaml 文件中添加多个文档 | PyYAML
【发布时间】:2019-04-08 14:19:57
【问题描述】:

我正在处理一个对象,首先 python 读取 YAML,进行一些更改,然后将它们写回文件。加载和更新值部分工作正常,但是当我去编写文件时,它会生成列表而不是单独的文档。

testing.yaml

apiVersion: v1
data:
  databag1: try this
  databag2: then try this
kind: ConfigMap
metadata:
  name: data bag info
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app: data-bag-service
  name: data-bag-tagging

代码块

import yaml
with open("./testing.yaml", "r") as stream:
    deployment_dict= list(yaml.safe_load_all(stream))

print(deployment_dict)
with open("./testing.yaml", "w") as service_config:
    yaml.dump(
        deployment_dict,
        service_config,
        default_flow_style=False
    )

我得到的转变: testing.yaml

- apiVersion: v1
  data:
    databag1: try this
    databag2: then try this
  kind: ConfigMap
  metadata:
    name: data bag info
- apiVersion: extensions/v1beta1
  kind: Deployment
  metadata:
    labels:
      app: data-bag-service
    name: data-bag-tagging

如何使用--- 指令结束指示符达到原始状态?

【问题讨论】:

  • --- 分隔符位于顶层,可以替代带有破折号的数组块。导出更喜欢数组块形式。
  • @KlausD。 --- 是指令结束指示符,即使没有指令也可以使用。我不确定您使用数组块指的是什么,但如果那是序列,但是一些关于为什么这个指标可能是替代品的参考(URL)会很有用。

标签: python python-3.x yaml pyyaml


【解决方案1】:

根据docs

如果您需要将多个 YAML 文档转储到单个流中,请使用函数 yaml.dump_allyaml.dump_all 接受列表或生成器生成

yaml.dump_all(
    deployment_dict,
    service_config,
    default_flow_style=False
)

您仍然需要default_flow_style=False 才能获得块样式输出。

示例代码:

import yaml


with open("./testing.yaml", "r") as stream:
    d = list(yaml.safe_load_all(stream))

d.append(d[-1])

with open("./testing2.yaml", "w") as stream:
    yaml.dump_all(
        d,
        stream,
        default_flow_style=False
    )

testing2.yaml

apiVersion: v1
data:
  databag1: try this
  databag2: then try this
kind: ConfigMap
metadata:
  name: data bag info
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app: data-bag-service
  name: data-bag-tagging
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app: data-bag-service
  name: data-bag-tagging

【讨论】:

    【解决方案2】:

    PyYAML 并不是真正为进行此类往返更新而设计的,它下降了 您可能拥有的任何 cmets,并且不一定保留键的顺序 映射。

    我建议你看看 ruamel.yaml(免责声明:我是 该软件包的作者)有几个原因,包括但不 限于:

    • 支持 YAML 1.2(但必要时可以写入/读取 YAML 1.1)
    • 保留 cmets、键顺序、锚点/别名、浮点数/整数格式
    • 更好地控制映射和列表的缩进
    • 无需加载所有文档,一次性处理和转储文件
    • 可选保留引号和/或块样式标量
    • 默认安全加载,如果你使用不安全load在 向后兼容的 API
    • 许多错误修复


    from pathlib import Path
    from ruamel.yaml import YAML
    
    path = Path('testing.yaml')
    tmp_path = path.with_suffix('.yaml.tmp')
    
    
    with YAML(output=tmp_path) as yaml:
        # yaml.indent(mapping=4, sequence=4, offset=2)
        # yaml.preserve_quotes = True
        for data in yaml.load_all(path):
            # update data
            yaml.dump(data)
    
    path.unlink()
    tmp_path.rename(path)
    
    print(path.read_text(), end='')
    

    给出:

    apiVersion: v1
    data:
      databag1: try this
      databag2: then try this
    kind: ConfigMap
    metadata:
      name: data bag info
    ---
    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      labels:
        app: data-bag-service
      name: data-bag-tagging
    

    请注意,您不能在与您相同的文件中读写 一次处理一个文档。因此临时文件 有额外的好处,如果你在更新时出错 最后一个文件和你的程序崩溃了,你不会剩下 一个写了一半的 YAML 流。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-01
      • 2012-02-28
      • 2021-05-17
      • 2015-12-06
      • 2011-10-12
      • 2013-10-19
      • 2012-12-16
      • 1970-01-01
      相关资源
      最近更新 更多