如何从python访问和修改yaml文件的内容?

How to access & modify the content of yaml file from python?

我想访问和修改如下所示的 YAML 文件的内容:

A: Sonstige
B:
  C: Sonstige
  D: null
  E: 1

我知道为了访问和修改上述 YAML 文件中 A 的值,我会使用如下代码:

def set_state(state):
    with open('my_file.yaml') as f:
        doc = yaml.load(f)

    doc['A'] = state

    with open('my_file.yaml', 'w') as f:
        yaml.dump(doc, f)

但是如果我想修改上面YAML文件中E的值呢?如何访问 E 的值并修改其值并将其转储到 YAML 文件中,类似于上面的代码。我已经查看了参考文档,但无法找到答案。

如果您想更改 E 的值,例如要 2,您可以执行以下操作:

import yaml

def set_state(state):
    with open('my_file.yaml') as f:
        doc = yaml.load(f)

    doc['B']['E'] = state

    with open('my_file.yaml', 'w') as f:
        yaml.dump(doc, f)

set_state(2)

获取 E 第一个索引的值 B

根据我的经验,这有很多问题:

  1. 您正在使用 load(),这在 PyYAML 中是一个没有警告的不安全操作。您的数据可以用 safe_load() 加载,即使不能,扩展 safe_load() 来处理标签(并且只处理那些标签)比扩展 load().[=38 要好得多=]

  2. 你的输出看起来像:

    A: Sonstige
    B: {C: Sonstige, D: null, E: 2}
    

    完全不像你的输入,所以使用选项 default_flow_style=False 用你原来的块式布局得到一些东西。

  3. 您不需要 dump(),因为由 dict 组成的数据和基元(和列表)可以用 safe_dump() 转储。那里没有安全问题,但是如果你不小心用非原始的方式调用 set_state()

    class Dice:
        def __init__(self, sides):
            self.sides = sides
    
    set_state(Dice(6))
    

    然后 dump() 将静默生成不可移植的:

    A: Sonstige
    B:
      C: Sonstige
      D: null
      E: !!python/object:__main__.Dice {sides: 6}
    

    而不是引发 Representer 错误。

  4. 原始文件中的任何评论都将丢失。 PyYAML 不保留这些。

使用 PyYAML,你应该这样做:

import yaml

def set_state(state):
    with open('my_file.yaml') as f:
        doc = yaml.safe_load(f)

    doc['B']['E'] = state

    with open('my_file.yaml', 'w') as f:
        yaml.safe_dump(doc, f, default_flow_style=False)

set_state(2)

如果你也想保留评论,或者你想保留块式和流式的混合,我建议你使用ruamel.yaml(免责声明:我是那个包的作者) :

import pathlib
from ruamel.yaml import YAML

def set_state(state):
    yaml = YAML()
    mf = pathlib.Path('my_file.yaml')
    doc = yaml.load(mf)

    doc['B']['E'] = state

    yaml.dump(doc, mf)

这与之前的结果相同,默认情况下 load() 方法是安全的,保留您的布局(加上您可能拥有的 YAML 文件中的任何注释)并打开 Path 实例根据需要进行阅读或写作(因此您不需要 with 语句,也不需要调用 dump 的双重操作并将 w 提供给 open())。