我试图将YAML文件拆分为两个不同的文件,如下所示:
def yaml_loader():
try:
with open("test.yaml", "r") as stream:
data = yaml.load(stream)
for workload in data:
with open(workload['workload']['name'] + '.yaml', 'a') as outfile:
yaml.dump(workload, outfile)
except yaml.YAMLError as out:
print(out)
YAML:
- workload:
name: c1
param:
p1: 1
p2: 2
- workload:
name: c2
param:
p1: 30
p2: 200
但是在输出中,对于YAML语法,两个文件都缺少-
。
workload:
name: c1
param:
p1: 1
p2: 2
我该如何解决这个问题?
答案 0 :(得分:2)
def yaml_loader():
try:
with open("test.yaml", "r") as stream:
data = yaml.load(stream)
for workload in data:
with open(workload['workload']['name'] + '.yaml', 'a') as outfile:
# if you put the variable "workload" in a list, you get the '-' in the yaml, as it denotes a list item.
yaml.dump([workload], outfile)
except yaml.YAMLError as out:
print(out)
in a yaml,
" - item:" 表示列表项,因此如果不将输出放在列表中,您将无法获得" - "
答案 1 :(得分:0)
您的代码未按预期运行,但也未按您的说明运行。
在第一次运行时,您将在c1.yaml
中获得此输出:
workload:
name: c1
param: {p1: 1, p2: 2}
因为默认情况下load()
和dump()
(在ruamel.yaml
和PyYAML中)将默认为不包含其他集合元素的集合元素(映射,序列)上的流样式。
此外,如果您第二次调用该例程,c1.yaml
文件将包含:
workload:
name: c1
param: {p1: 1, p2: 2}
workload:
name: c1
param: {p1: 1, p2: 2}
因为你打开追加。
如果您无法控制文件来源并且可能包含YAML标记,则使用load()
进行此类拆分文件可能也不是一个好主意。
上述问题是在缺失的顶层序列元素之上,可以很容易地解决,如@Ignacio Vazquez-Abrams所示。
也没有必要将for语句放在第一个with
语句中,从而延迟关闭输入文件。 data
不是迭代器。
我建议使用ruamel.yaml
¹往返加载/转储来做到这一点。除了保留块resp。流式,它还支持YAML 1.2,保留您的注释,保留映射键的顺序,并可以在源中保留标量字符串的引号:
import ruamel.yaml as yaml
def yaml_loader():
try:
with open("test.yaml", "r") as stream:
data = yaml.round_trip_load(stream, preserve_quotes=True)
for workload in data:
with open(workload['workload']['name'] + '.yaml', 'w') as outfile:
yaml.round_trip_dump([workload], outfile)
except yaml.YAMLError as out:
print(out)
yaml_loader()
会给你:
- workload:
name: c1
param:
p1: 1
p2: 2
¹这是使用ruamel.yaml完成的,我是作者。