如何在Python中的ruamel.yaml中的空yaml文件中插入键值对?
How to insert a key value pair in an empty yaml file in ruamel.yaml in Python?
我的objective是在可能为空的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()
但是当我的hiera.yaml文件不为空时,例如:
$ cat hiera.yaml
john:
$./alice.py Alice Doe Developer
$ cat hiera.yaml
john:
alice:
first_name: Alice
last_name: Doe
role: Developer
然后就正常了
请告诉我如何将键值对(在我的例子中是一个字典)插入一个空的 YAML 文件。 ruamel.yaml官网示例使用doc string作为示例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 ... 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
也可以!
YAML 文档中的空标量为您提供了 null
YAML 对象,该对象作为 None
:
加载到 Python
a: 1
b:
从此加载的数据中键 b
的值将为 None
。
使用 ruamel.yaml 从中加载数据的空文件或空字符串被视为与包含标量 null
:[=24 的 file/string 相同=]
null
如果你加载它,你会 None
回来,你不能向它添加新的密钥。
确保检查您加载的数据是 dict
还是字典的子类(如果您使用 round_trip_load 加载,您将得到 ruamel.yaml.comment .CommentedMap), 或者检查它是否是 None:
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()
,而后者(列表)只接受 .insert()
的单个参数
我的objective是在可能为空的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()
但是当我的hiera.yaml文件不为空时,例如:
$ cat hiera.yaml
john:
$./alice.py Alice Doe Developer
$ cat hiera.yaml
john:
alice:
first_name: Alice
last_name: Doe
role: Developer
然后就正常了
请告诉我如何将键值对(在我的例子中是一个字典)插入一个空的 YAML 文件。 ruamel.yaml官网示例使用doc string作为示例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 ... 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
也可以!
YAML 文档中的空标量为您提供了 null
YAML 对象,该对象作为 None
:
a: 1
b:
从此加载的数据中键 b
的值将为 None
。
使用 ruamel.yaml 从中加载数据的空文件或空字符串被视为与包含标量 null
:[=24 的 file/string 相同=]
null
如果你加载它,你会 None
回来,你不能向它添加新的密钥。
确保检查您加载的数据是 dict
还是字典的子类(如果您使用 round_trip_load 加载,您将得到 ruamel.yaml.comment .CommentedMap), 或者检查它是否是 None:
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()
,而后者(列表)只接受 .insert()