В отображаемом сообщении об ошибке отсутствует номер строки (я предполагаю, что это 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
до того, как будет сгенерировано исключение, и я надеюсь, что вы поймете, что вы не выполняете итерации по elem ents (элементы) списка, но поверх ключа s 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()