如何在python中添加新键值到yaml而不覆盖它?

ltskdhd1  于 2022-12-05  发布在  Python
关注(0)|答案(1)|浏览(141)

我有小的Python脚本,负责通过添加新记录来更新我的yaml文件:

data = yaml.load(file)
data['WIN']['Machine'] = dict(node_labels='+> tfs vs2022')
data['WIN']['Machine'] = dict(vs='vs2022')
yaml.dump(data, file)

每次当我运行上面的脚本,我会得到更新的yaml文件如下:

WIN:
  Machine:
    vs: vs2022

我想要的输出同时包含我的密钥:值对

WIN:
  Machine:
    node_labels: +> tfs vs2022
    vs: vs2022

我很奇怪为什么data['WIN'][nodeName] = dict(node_labels='+> tfs vs2022')行被下一行覆盖了?怎么可以加几个键:Machine区段的值?

gzszwxb4

gzszwxb41#

这不是一个与YAML相关的问题,而是一个与yaml无关的Python代码中的概念问题。
通过给键Machine赋一个dict作为值,你设置了那个值。通过给键赋另一个dict,你完全覆盖了那个值,擦除了以前的键值对。
如果简化代码:

data = dict(Machine=None)
data['Machine'] = dict(node_labels='+> tfs vs2022')
print('data 1', data)
data['Machine'] = dict(vs='vs2022')
print('data 2', data)

正如您在第二次赋值后所看到的,键node_labels不再可用。

data 1 {'Machine': {'node_labels': '+> tfs vs2022'}}
data 2 {'Machine': {'vs': 'vs2022'}}

有几种方法可以解决这个问题。你可以给第一个字典中的键赋值:

data = dict(Machine=None)
data['Machine'] = added_dict = dict(node_labels='+> tfs vs2022')
print('data 1', data)
added_dict['vs'] ='vs2022'
print('data 2', data)

现在,您在第二个输出中有了两个密钥:

data 1 {'Machine': {'node_labels': '+> tfs vs2022'}}
data 2 {'Machine': {'node_labels': '+> tfs vs2022', 'vs': 'vs2022'}}

如果你还不知道有一个字典可以添加一个键,你可以使用.setdefault,或者使用键值赋值,和/或使用.update(对于一次更新多个键很有用):
第一个
当然,你可以把node_labelsvs放在一个dict中并赋值,但是这会覆盖从YAML加载的任何现有键值。所以使用.update是IMO更好的选择:

import sys
from pathlib import Path
import ruamel.yaml

file_in = Path('input.yaml')
# key in YAML mapping with null value
file_in.write_text("""\
WIN:
""")
    
yaml = ruamel.yaml.YAML()
data = yaml.load(file_in)
if data['WIN'] is None:
    data['WIN'] = {}
data['WIN'].setdefault('Machine', {}).update(dict(node_labels='+> tfs vs2022'))
data['WIN'].setdefault('Machine', {}).update(dict(vs='vs2022'))
yaml.dump(data, sys.stdout)

这将给出预期结果:

WIN:
  Machine:
    node_labels: +> tfs vs2022
    vs: vs2022

相关问题