Динамически изменяйте yaml и сохраняйте все форматирование и комментарии - python - PullRequest
0 голосов
/ 07 февраля 2020

У меня есть файл config.yml, подобный этому:

# CONFIGURATION FILE
# COMMENT 1 blah 
# COMMENT 2 blah blah
# COMMENT 3 blah blah blah

NAME: Fruits

# CONFIGURATION FILE
# COMMENT 4 blah 
# COMMENT 5 blah blah
# COMMENT 6 blah blah blah

fruit_list:
  - "apple-01:9100"

Я хочу динамически изменить fruit_list. Я хочу добавить введенные пользователем данные из flask веб-формы. Ниже приведен код, который я пробовал, я могу изменить только одну строку с этим кодом.

import ruamel.yaml
from ruamel.yaml import YAML

yaml = YAML()
conf_file = pathlib.Path('configs/config.yml')
conf_key = yaml.load(conf_file)
conf_key['Fruits'] = form.bsa.data
conf_key['fruit_list'] = form.fqdn.data + ':9100'
yaml.dump(conf_key, conf_file)

Приведенный выше код позволяет мне изменять / добавлять только одну строку к fruit_list. Кроме того, он не сохраняет форматирование. Комментарии сохраняются, но интервал беспорядок и продолжает увеличиваться. Смотрите вывод ниже:

# CONFIGURATION FILE

# COMMENT 1 blah 

# COMMENT 2 blah blah

# COMMENT 3 blah blah blah

NAME: Fruits

# CONFIGURATION FILE
# COMMENT 4 blah 
# COMMENT 5 blah blah
# COMMENT 6 blah blah blah

fruit_list: apple-01:9100

Желаемый результат будет следующим:

# CONFIGURATION FILE
# COMMENT 1 blah 
# COMMENT 2 blah blah
# COMMENT 3 blah blah blah

NAME: Fruits

# CONFIGURATION FILE
# COMMENT 4 blah 
# COMMENT 5 blah blah
# COMMENT 6 blah blah blah

fruit_list:
  - "apple-01:9100"
  - "orange-01:9100"
  - "pear-01:9100"
  - "grape-01:9100"

Я бы также хотел, чтобы добавление в fruit_list было динамическим c в зависимости от того, сколько fruits пользователь ввел.

1 Ответ

1 голос
/ 09 февраля 2020

Я думаю, что что-то не так с вашим вводом YAML (кроме использования расширения .yml, с 2006 года рекомендуемое расширение для файлов YAML было .yaml). Я подозреваю, что ваши входные данные имеют некоторые дополнительные возвраты кариеса или что-то еще, поэтому убедитесь, что вы проверили это, выполнив print(repr(conf_key)) и возможно

conf_key = conf_key.replace('\r', '\n')

или подобное, чтобы очистить вещи. Как показано ниже, я не могу воспроизвести получение дополнительных новых строк

Что касается добавления в последовательность YAML, если вы хотите, чтобы вы добавляли соответствующий список в Python. И не назначайте новое значение, не относящееся к списку, ключу родительского dict:

import sys
import pathlib
import ruamel.yaml

conf_file = pathlib.Path('config.yaml')


conf_file.write_text("""\
# CONFIGURATION FILE
# COMMENT 1 blah 
# COMMENT 2 blah blah
# COMMENT 3 blah blah blah

NAME: Fruits

# CONFIGURATION FILE
# COMMENT 4 blah 
# COMMENT 5 blah blah
# COMMENT 6 blah blah blah

fruit_list:
  - "apple-01:9100"
""")

yaml = ruamel.yaml.YAML()
yaml.indent(sequence=4, offset=2)
conf_key = yaml.load(conf_file)
conf_key['Fruits'] = 'some_data'
conf_key['fruit_list'].append('orange-01:9100')
conf_key['fruit_list'].extend(['pear-01:9100', 'grape-01:9100'])
yaml.dump(conf_key, sys.stdout)

, что дает:

# CONFIGURATION FILE
# COMMENT 1 blah 
# COMMENT 2 blah blah
# COMMENT 3 blah blah blah

NAME: Fruits

# CONFIGURATION FILE
# COMMENT 4 blah 
# COMMENT 5 blah blah
# COMMENT 6 blah blah blah

fruit_list:
  - apple-01:9100
  - orange-01:9100
  - pear-01:9100
  - grape-01:9100
Fruits: some_data

С вашим кодом вы также должны ожидать дополнительный ключ Fruits в сопоставлении уровней root.

В общем случае во время тестирования лучше записывать в другой файл или стандартный вывод: не нужно восстанавливать исходный ввод.

...