Как обновить этот файл yaml с помощью python и ruamel?

У меня есть файл test.yaml с содержимым:

school_ids:
  school1: "001"

  #important school2
  school2: "002"


targets:
  neighborhood1:
    schools:
      - school1-paloalto
    teachers:
      - 33
  neighborhood2:
    schools:
      - school2-paloalto
    teachers:
      - 35

Я хочу использовать ruamel для обновления файла, чтобы он выглядел так:

school_ids:
  school1: "001"

  #important school2
  school2: "002"

  school3: "003"


targets:
  neighborhood1:
    schools:
      - school1-paloalto
    teachers:
      - 33
  neighborhood2:
    schools:
      - school2-paloalto
    teachers:
      - 35
  neighborhood3:
    schools:
      - school3-paloalto
    teachers:
      - 31

Как мне использовать ruamel для обновления файла, чтобы получить желаемый результат, сохранив комментарии?

Вот что у меня есть до сих пор:

import sys
from ruamel.yaml import YAML

inp = open('/targets.yaml', 'r').read()

yaml = YAML()

code = yaml.load(inp)
account_ids = code['school_ids']
account_ids['new_school'] = "003"
#yaml.dump(account_ids, sys.stdout)


targets = code['targets']
new_target = dict(neighborhood3=dict(schools=["school3-paloalto"], teachers=["31"]))
yaml = YAML()
yaml.indent(mapping=2, sequence=3, offset=2)
yaml.dump(new_target, sys.stdout)

person Becks    schedule 28.01.2021    source источник


Ответы (1)


Вы просто сбрасываете new_target, который создаете с нуля, не используя code или даже targets. Вместо этого вы должны либо использовать тот code, который вы загрузили, и расширить значения, связанные с его ключами корневого уровня, а затем выгрузить code:

import sys
from pathlib import Path
from ruamel.yaml import YAML

inp = Path('test.yaml')

yaml = YAML()

code = yaml.load(inp)
school_ids = code['school_ids']
school_ids['school3'] = "003"


targets = code['targets']
targets['neighborhood3'] = dict(schools=["school3-paloalto"], teachers=["31"])
yaml = YAML()
yaml.indent(mapping=2, sequence=4, offset=2)
yaml.dump(code, sys.stdout)

который дает:

school_ids:
  school1: '001'

  #important school2
  school2: '002'


  school3: '003'
targets:
  neighborhood1:
    schools:
      - school1-paloalto
    teachers:
      - 33
  neighborhood2:
    schools:
      - school2-paloalto
    teachers:
      - 35
  neighborhood3:
    schools:
      - school3-paloalto
    teachers:
      - '31'

Обратите внимание, что отступ вашей последовательности должен быть как минимум на 2 больше, чем ваше смещение (2 позиции, чтобы было место для - + ПРОБЕЛ).

В выводе есть пустые строки после ключа school2, так как это то, с чем они связаны во время синтаксического анализа. Это можно перенести на новый ключ, но это не тривиально. Если вам нужно это сделать (это не важно для семантики документа YAML), посмотрите мой ответ здесь

person Anthon    schedule 28.01.2021
comment
Спасибо за ваш добрый и быстрый ответ @Anthon. Я заметил, что в примере, которому я следую также в вашем ответе, мы печатаем в sys.stdout. Есть ли способ обновить тот же файл и записать в него обновленные поля и значения? используя тот же модуль ruamel, который есть. Базово обновите файл... Заранее спасибо!!! - person Becks; 29.01.2021
comment
@Becks Если вы используете экземпляр pathlib.Path (как я), обратная запись в файл так же проста, как выполнение yaml.dump(code, inp). Соответствующее открывает и закрывает файл для вас. Создайте новый Path, если вывод должен идти в другой файл (или рассмотрите возможность переименования inp, если вам нужно сохранить содержимое старого файла) - person Anthon; 29.01.2021