如何根据 python 键的值将 YAML 解析为多个 compose.yaml
How can I parse YAML into multiple compose.yaml based on the value of a key with python
我正在解析 YAML 并将其分解为多个不同的 YAML 文件。我是用PyYAML的constructor实现的,但是效果很差
这是我项目的一部分,我需要根据收到的 yaml 文件中的键值解析并拆分为多个不同的 yaml 文件。
我收到的 yaml 文件看起来像这样
testname: testname
testall:
test1:
name: name1
location: 0
test2:
name: name2
location: 2
test3:
name: name3
location: 0
test4:
name: name4
location: 2
...
locations:
- 0
- 2
- ...
我想解析它并按设备拆分,如下所示:
# location0.yaml
testname:test
tests:
test1:
name:test1
location:0
test3:
name: test3
location: 0
# location2.yaml
testname:test
tests:
test2:
name:test2
location:0
test4:
name: test4
location: 0
如何像上面的形式解析?
尽管您可以使用 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
我正在解析 YAML 并将其分解为多个不同的 YAML 文件。我是用PyYAML的constructor实现的,但是效果很差
这是我项目的一部分,我需要根据收到的 yaml 文件中的键值解析并拆分为多个不同的 yaml 文件。
我收到的 yaml 文件看起来像这样
testname: testname
testall:
test1:
name: name1
location: 0
test2:
name: name2
location: 2
test3:
name: name3
location: 0
test4:
name: name4
location: 2
...
locations:
- 0
- 2
- ...
我想解析它并按设备拆分,如下所示:
# location0.yaml
testname:test
tests:
test1:
name:test1
location:0
test3:
name: test3
location: 0
# location2.yaml
testname:test
tests:
test2:
name:test2
location:0
test4:
name: test4
location: 0
如何像上面的形式解析?
尽管您可以使用 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