如何读取YAML文件中的组件,以便可以使用ruamel.yaml编辑它的键值? [英] How to read a component in YAML file so that I can edit it's key value using ruamel.yaml?

查看:310
本文介绍了如何读取YAML文件中的组件,以便可以使用ruamel.yaml编辑它的键值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的YAML文件(input.yaml):

This is my YAML file (input.yaml):

team_member:
  name: Max
  hobbies:
    - Reading

team_leader:
  name: Stuart
  hobbies:
    - dancing

我想编辑此YAML文件以在关键的爱好"中添加更多值,例如:

I want to edit this YAML file to add more values in key 'hobbies', example:

team_member:
  name: Max
  hobbies:
    - Reading
    - Painting

team_leader:
  name: Stuart
  hobbies:
    - Dancing
    - Fishing

我尝试实现代码 Anthon 以适应我的情况,但是它根本没有帮助,因为缩进级别为该YAML文件与我的文件不同.
示例:

I tried to implement the code Anthon to fit my situation but it didn't helped at all, because the indention level of that YAML file is different from mine.
Example:

import sys
import ruamel.yaml

yaml = ruamel.yaml.YAML()
# yaml.preserve_quotes = True
with open('input.yaml') as fp:
    data = yaml.load(fp)
for elem in data:
    if elem['name'] == 'Stuart':
         elem['hobbies'] = ['Fishing']
         break  # no need to iterate further
yaml.dump(data, sys.stdout)

我收到错误消息"TypeError('字符串索引必须是整数',)",我知道这段代码可能是完全错误的,但是我对ruamel.yaml还是陌生的.

I get error "TypeError('string indices must be integers',)", I know this code might be completely wrong, but I am new to ruamel.yaml.

该如何编码?

推荐答案

错误消息显示的内容是行号(我假设它是9).指向该行

The thing missing form the error message displayed is the line number (I assume that it is 9). That points to the line

    if elem['name'] == 'Stuart':

如果这没有给您任何线索,那么在这种情况下,我推荐的方法是开始添加一些print函数,以便您知道自己在做什么. for循环如下:

And if that doesn't give you a clue, the approach that I recommend in such cases is starting to add some print functions, so that you know what you are working on. The for loop looks like:

for elem in data:
    print('elem', elem)
    if elem['name'] == 'Stuart':
         print('elem->hobbies', elem['hobbies'])
         elem['hobbies'] = ['Fishing']

此打印

 elem team_member

在引发异常之前,我希望这会让您意识到您不是在遍历列表的 项(项目),而是在 key 上进行迭代的s(从YAML中的根级别映射构造).与键关联的 value 是具有键name和键hobbies的对象.

before the exception is thrown, and I hope that will make you realize your are not iterating over the elements (items) of a list, but over the keys of a dict (constructed from the root level mapping in your YAML). And the value associated with the key is the object having a key name and a key hobbies.

因此,将变量elem更改为key以明确您要处理的内容,然后继续使用value(与该键关联的值而不是该循环内的elem)

So change the variable elem to key to make clear what you're handling and then proceed to work with value, the value associated with that key instead of elem within that loop¹:

for key in data:
    value = data[key]
    if value['name'] == 'Stuart':
         print('value->hobbies', value['hobbies'])
         value['hobbies'] = ['Fishing']

这给出了:

value->hobbies ['dancing']
team_member:
  name: Max
  hobbies:
  - Reading

team_leader:
  name: Stuart
  hobbies:
  - Fishing

因此,我们摆脱了异常,但结果并非完全符合您的要求.密钥爱好"的元素dancing消失了,因为您为该密钥分配了一个新的(列表)值,而您应该做的是将单个项目附加到列表中.我们现在也可以摆脱打印功能:

So we got rid of the exception, but the result is not exactly what you want. The element dancing for the key 'hobbies' is gone, because you assign a new (list) value to that key, whereas what you should do is append a single item to the list. We can also get rid of the print function by now:

for key in data:
    value = data[key]
    if value['name'] == 'Stuart':
         value['hobbies'].append('Fishing')

这将使您在文件的最后顺序中得到两项.还有其他一些事情要解决:

This will get you two items in the final sequence in the file. There is a few more things to address:

  • dancing的大写不正确.要更正此问题,请在只有一个元素的情况下添加一行处理列表
  • 需要添加名称为Max的代码(这就是为什么您需要删除代码中的break的原因)
  • 空行被视为对第一个序列的最后一个元素的注释,该注释需要移动
  • 您的序列缩进不是默认值
  • the capitalization of dancing incorrect. To correct that, add a line handling the list if there is only one element
  • the code for the name Max, needs to be added (and that is why you need to get rid of the break in your code)
  • the empty line, is considered a comment on the last element of the first sequence, that comment needs to be moved
  • your indentation of sequences is non-default

最终代码如下:

from pathlib import Path
import ruamel.yaml

path = Path('input.yaml')
yaml = ruamel.yaml.YAML()
yaml.indent(sequence=4, offset=2)  # for the non-default indentation of sequences

data = yaml.load(path)
for key in data:
    value = data[key]
    if value['name'] == 'Stuart':
         if len(value['hobbies']) == 1:
             value['hobbies'][0] = value['hobbies'][0].capitalize()
         value['hobbies'].append('Fishing')
    elif value['name'] == 'Max':
         last_item_index = len(value['hobbies']) - 1
         value['hobbies'].append('Painting')
         comments = value['hobbies'].ca
         if not comments.items[last_item_index][0].value.strip():
             # move empty comment lines from previous last item to new last item
             comments.items[last_item_index + 1] = comments.items.pop(last_item_index)

yaml.dump(data, path)

哪些产品与您想要获得的产品非常接近

Which gives something quite close to what you wanted to get

team_member:
  name: Max
  hobbies:
    - Reading
    - Painting

team_leader:
  name: Stuart
  hobbies:
    - Dancing
    - Fishing


¹前两行的替代:for key, value in data.items()


¹Alternative for the first two lines: for key, value in data.items()

这篇关于如何读取YAML文件中的组件,以便可以使用ruamel.yaml编辑它的键值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆