分割.yml文件

时间:2018-12-26 15:59:40

标签: python python-3.x parsing yaml edit

我需要将.yml文件分解为3个部分:页眉,工作(我需要编辑的部分)和页脚。标头是“ Resource:”块之前的所有内容,而页脚是资源块之后的所有内容。本质上,我需要创建代码来创建3个列表,字典,字符串,无论做什么工作,这些代码都保存YAML文件的这三个部分,然后允许我针对该工件运行更多代码,然后将所有代码最后连接在一起,产生具有相同缩进的新文档。不应更改标题或尾部。

注意:我已经查找了有关yaml解析的所有内容,但似乎无法有效地实现我发现的建议。首选不涉及导入yaml的解决方案,但是如果您必须这样做,请解释一下导入yaml代码的真正含义,以便我理解我的理解。

1 个答案:

答案 0 :(得分:0)

包含一个或多个YAML文档(简称:YAML文件,自 建议您在2006年9月使用扩展名.yaml) 文本文件,并且可以从各个部分进行串联。唯一的要求是 最后,您将获得一个文本文件,该文件是有效的YAML文件。

最简单的当然是将页眉和页脚分开 文件,但是当您谈论多个YAML文件时, 很快变得笨拙。但是总是可以做一些基本的 解析文件内容。

由于您的工作部分以Resource:开头,因此您指定了3 列表或字典(一个字符串的根不能有三个字符串 YAML文件)。 YAML文档的根级别数据结构 必须是 mapping 以及其他所有内容,除了 映射的键需要缩进(理论上,它只需要 缩进更多,但实际上这几乎总是意味着 键不缩进),例如(m.yaml):

# header
a: 1
b:
  - 2
  - c: 3    # end of header
Resource:
# footer
c: 
d: "the end"   # really

或根级别必须是一个序列(s.yaml):

# header
- a: 1
  b:
  - 2
  - c: 3
- 42         # end of header
- Resource:
# footer
- c: 
  d: "the end"  # really

两者都可以很容易地拆分,而无需加载YAML,这是为此的示例代码 具有根级别映射的文件:

from pathlib import Path
from ruamel.yaml import YAML

inf = Path('m.yaml')
header = []  # list of lines
resource = [] 
footer = []
for line in inf.open():
    if not resource:
        if line.startswith('Resource:'):  # check if we are at end of the header
            resource.append(line)
            continue
        header.append(line)
        continue
    elif not footer:
        if not line or line[0] == ' ':   # still in the resource part
            resource.append(line)
            continue
    footer.append(line)

# you now have lists of lines for the header and the footer
# define the new data structure for the resource this is going to be a single key/value dict
upd_resource = dict(Resource=['some text', 'for the resource spec', {'a': 1, 'b': 2}])

# write the header lines, dump the resource lines, write the footer lines

outf = Path('out.yaml')

with outf.open('w') as out:
    out.write(''.join(header))
    yaml = YAML()
    yaml.indent(mapping=2, sequence=2, offset=0)  # the default values
    yaml.dump(upd_resource, out)
    out.write(''.join(footer))

print(outf.read_text())

这给出了:

# header
a: 1
b:
  - 2
  - c: 3    # end of header
Resource:
- some text
- for the resource spec
- a: 1
  b: 2
# footer
c: 
d: "the end"   # really

在解析YAML文件的同时执行相同操作并不困难。以下自动处理 两种情况(根级别是映射还是序列):

from pathlib import Path
from ruamel.yaml import YAML

inf = Path('s.yaml')
upd_resource_val = ['some text', 'for the resource spec', {'a': 1, 'b': 2}]
outf = Path('out.yaml')


yaml = ruamel.yaml.YAML()
yaml.indent(mapping=2, sequence=2, offset=0)
yaml.preserve_quotes = True
data = yaml.load(inf)
if isinstance(data, dict):
    data['Resource'] = upd_resource_val
else:  # assume a list, 
    for item in data:  # search for the item which has as value a dict with key Resource
        try:
            if 'Resource' in item:
                item['Resource'] = upd_resource_val
                break
        except TypeError:
            pass
yaml.dump(data, outf)

这将创建以下out.yaml

# header
- a: 1
  b:
  - 2
  - c: 3
- 42         # end of header
- Resource:
  - some text
  - for the resource spec
  - a: 1
    b: 2
# footer
- c:
  d: "the end"  # really

如果已输入m.yaml文件,则输出将具有 与基于文本的“串联”示例代码完全相同。