繁体   English   中英

如何读取 YAML 文件中的组件以便我可以使用 ruamel.yaml 编辑它的键值?

[英]How to read a component in YAML file so that I can edit it's key value using ruamel.yaml?

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

team_member:
  name: Max
  hobbies:
    - Reading

team_leader:
  name: Stuart
  hobbies:
    - dancing

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

team_member:
  name: Max
  hobbies:
    - Reading
    - Painting

team_leader:
  name: Stuart
  hobbies:
    - Dancing
    - Fishing

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

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 的新手。

如何编码?

显示的错误消息中缺少的是行号(我假设它是 9)。 那指向那条线

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

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

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

这打印

 elem team_member

在抛出异常之前,我希望这会让您意识到您不是在迭代列表的元素(项目),而是在 dict 的键上迭代(从 YAML 中的根级映射构建)。 与键关联的是具有键name和键hobbies

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

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的元素消失了,因为您为该键分配了一个新的(列表)值,而您应该做的是将单个项目附加到列表中。 我们现在也可以去掉打印功能:

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

这将为您提供文件中最终序列中的两个项目。 还有一些事情要解决:

  • dancing的大小写不正确。 要纠正这一点,如果只有一个元素,请添加一行处理列表
  • 需要添加名称Max的代码(这就是为什么您需要摆脱代码中的break
  • 空行,被认为是对第一个序列的最后一个元素的注释,该注释需要移动
  • 您的序列缩进是非默认的

最终代码如下:

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)

这给出了非常接近你想要的东西

team_member:
  name: Max
  hobbies:
    - Reading
    - Painting

team_leader:
  name: Stuart
  hobbies:
    - Dancing
    - Fishing

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

感谢 Anthon,您的代码有效,我必须按如下方式编辑此代码:

import sys
import ruamel.yaml
from pathlib import Path

yaml = ruamel.yaml.YAML()
path = Path('input.yaml')
yaml.indent(sequence=4, offset=2)  # for the non-default indentation of sequences
with open(path) as fp:
    data = yaml.load(fp)
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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM