如何在Python中的ruamel.yaml中的空yaml文件中插入键值对?

如何在Python中的ruamel.yaml中的空yaml文件中插入键值对?,python,yaml,hiera,ruamel.yaml,Python,Yaml,Hiera,Ruamel.yaml,我的目标是在YAML文件中插入一个可能为空的键值对 例如,我的hiera.yaml(用于puppet)文件只包含三个连字符 这是我的密码: #!/usr/bin/python import ruamel.yaml import sys def read_file(f): with open(f, 'r') as yaml: return ruamel.yaml.round_trip_load(yaml) dict = {} dict['first_name'] = sys.ar

我的目标是在YAML文件中插入一个可能为空的键值对

例如,我的
hiera.yaml
(用于puppet)文件只包含三个连字符

这是我的密码:

#!/usr/bin/python
import ruamel.yaml
import sys

def read_file(f):
  with open(f, 'r') as yaml:
    return ruamel.yaml.round_trip_load(yaml)

dict = {}

dict['first_name'] = sys.argv[1]
dict['last_name'] = sys.argv[2]
dict['role'] = sys.argv[3]

data = read_file('hiera.yaml')

pos = len(data)
data.insert(pos, sys.argv[1], dict, None)


ruamel.yaml.round_trip_dump(data, open('hiera.yaml', 'w'), block_seq_indent=1)
我是这样运行的:

./alice.py alice Doe开发者

我得到如下输出:

Traceback (most recent call last):
  File "./alice.py", line 16, in <module>
    pos = len(data)
TypeError: object of type 'NoneType' has no len()
然后它就正常工作了


请告诉我如何将键值对(在我的例子中是dict)插入空YAML文件。ruamel.yaml官方页面的示例使用doc字符串作为示例yaml内容,然后插入键值对。

您没有正确处理数据为空的可能性。以下是解决此问题的方法:

import ruamel.yaml
import sys


def read_file(f):
    with open(f, 'r') as yaml:
        return ruamel.yaml.round_trip_load(yaml)

new_dict = {}

new_dict['first_name'] = sys.argv[1]
new_dict['last_name'] = sys.argv[2]
new_dict['role'] = sys.argv[3]

data = read_file('hiera.yaml')
try:
    pos = len(data)
    data.insert(pos, sys.argv[1], dict, None)


except TypeError:
    pass

ruamel.yaml.round_trip_dump(new_dict, open('hiera.yaml', 'a'),
                            block_seq_indent=1)
请注意
try。。。除了

另外请注意,我正在以追加模式打开文件。否则,内容将被删除(如果已经存在)

演示时间:

 $ cat hiera.yaml 
 Jon:
 $ python test.py  Alice Doe Developer
 cat hiera.yaml 
 Jon:
 first_name: Alice
 role: Developer
 last_name: Doe
这对现有数据有效。 现在,让我们使用一个空文件进行测试:

 $ rm hiera.yaml 
 $ touch hiera.yaml
 $ python test.py  Alice Doe Developer
 $ cat hiera.yaml 
 first_name: Alice
 role: Developer
 last_name: Doe

也行

YAML文档中的空标量为您提供作为
None
加载到Python中的
null
YAML对象:

a: 1
b: 
从中加载的数据中键
b
的值将为
None

使用ruamel.yaml从中加载数据的空文件或空字符串被视为与包含标量
null
的文件/字符串相同:

null
如果您加载了它,您将返回
None
,并且您不能向其中添加新键

确保检查您加载的数据是否是dict的
dict
或dict的子类(如果您使用往返加载,您将获得ruamel.yaml.comment.CommentedMap),或者检查它是否为无:

 data = ruamel.yaml.round_trip_load(open('myfile.yaml'))
 if data is None:
     data = ruamel.yaml.comments.CommentedMap()
 data.insert(len(data), key, value)
您必须使用
CommentedMap()
,因为普通Python dict没有方法
。insert()


注意,YAML文件中的顶级项也可能是标量(字符串、整数、日期时间等)或序列(作为列表加载)。前者可能无法
.inserted()
,而后者(列表)只接受
.inserte()

的一个参数。谢谢Oz123和Anthon。但是,Anthon的答案更适合我。Oz123我有点担心您使用opening作为附加。IMO不应该对YAML文件执行此操作,如果执行此操作,可能会使文件不可加载(即不正确的YAML)。
 data = ruamel.yaml.round_trip_load(open('myfile.yaml'))
 if data is None:
     data = ruamel.yaml.comments.CommentedMap()
 data.insert(len(data), key, value)