Хотя вы можете сделать это с PyYAML, вам придется ограничить
себя в YAML 1.1. Для этого типа чтения-изменения-записи вы должны
используйте ruamel.yaml
(отказ от ответственности: я являюсь автором этого пакета). Не
поддерживает только YAML 1.2, сохраняет комментарии, теги
и якорные имена в случае, если они встречаются в вашем источнике и могут сохранить
кавычки вокруг скаляров, буквального и сложенного стиля и т. д., если вам это нужно.
Также обратите внимание, что ваш вывод неверен YAML, вы не можете иметь
многострочный (то есть без кавычек) скалярный ключ (стиль блока)
отображение. Вам нужно написать:
"testname:test
tests":
но я предполагаю, что вы имели в виду два ключа для сопоставления корневого уровня:
testname: test
tests:
Предполагая, что ваш ввод в input.yaml
:
testname: testname
testall:
test1:
name: name1 # this is just the first name
location: 0
test2:
name: "name2" # quotes added for demo purposes
location: 2
test3:
name: name3 # as this has the same location as name1
location: 0 # these should be together
test4:
name: name4 # and this one goes with name2
location: 2
locations:
- 0
- 2
Вы можете сделать:
import sys
from pathlib import Path
import ruamel.yaml
in_file = Path('input.yaml')
yaml = ruamel.yaml.YAML()
yaml.indent(mapping=4, sequence=6, offset=4) # this matches your input
yaml.preserve_quotes = True
data = yaml.load(in_file)
for loc in data['locations']:
out_name = f'location{loc}.yaml'
tests = {}
d = ruamel.yaml.comments.CommentedMap(dict(testname="test", tests=tests))
d.yaml_set_start_comment(out_name)
testall = data['testall']
for test in testall:
if loc == testall[test]['location']:
tests[test] = testall[test]
tests[test]['location'] = 0
# since you set location to zero and this affects data, make sure to remove
# the items. This will prevent things from going wrong in case the
# locations sequence does have zero, but not as its first number
for key in tests:
del testall[key]
yaml.dump(d, Path(out_name))
, что дает location0.yaml
:
# location0.yaml
testname: test
tests:
test1:
name: name1 # this is just the first name
location: 0
test3:
name: name3 # as this has the same location as name1
location: 0 # these should be together
и location2.yaml
:
# location2.yaml
testname: test
tests:
test2:
name: "name2" # quotes added for demo purposes
location: 0
test4:
name: name4 # and this one goes with name2
location: 0