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

时间:2017-06-07 16:22:10

标签: python yaml pyyaml

我想访问和修改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文件中,类似于上面的代码。我已经查阅了参考文档,但无法找到答案。

1 个答案:

答案 0 :(得分:2)

如果您想更改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()

  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不保留这些。

  5. 使用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(免责声明:我是该套餐的作者):< / p>

    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()