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

时间:2017-02-15 09:02:25

标签: 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.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 Developer

我得到的输出如下:

Traceback (most recent call last):
  File "./alice.py", line 16, in <module>
    pos = len(data)
TypeError: object of type 'NoneType' has no len()

但是当我的hiera.yaml文件不为空时,例如:

$ cat hiera.yaml
john:
$./alice.py Alice Doe Developer
$ cat hiera.yaml
john:
alice:
  first_name: Alice
  last_name: Doe
  role: Developer

然后它正常工作。

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

2 个答案:

答案 0 :(得分:0)

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

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 ... except阻止。

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

演示时间:

 $ 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

也一样!

答案 1 :(得分:0)

YAML文档中的空标量为您提供 body{ background-color: #fbfbfb; } input.ng-invalid { border:2px solid #EA4335; } input.ng-valid { background-color:lightgreen; } input{ width:800px; height:60px; text-align: center; font-size: 30px } YAML对象,该对象作为null加载到Python中:

None

从此加载的数据中的密钥a: 1 b: 的值为b

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

null

如果你加载它,你会得到null ,而你无法添加新密钥。

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

dict

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

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

的单个参数