Изменение содержимого YAML

#python #yaml

#python #yaml

Вопрос:

У меня есть файл YAML, подобный приведенному ниже. Файл содержит некоторые специальные символы, такие как «—«, поэтому я не могу загрузить YAML в python с помощью yaml.load() метода.

 _engine: E1
_parameter:
- capacity:
  - updated: 20200825
    dependent: []
---
_engine: E2
_parameter:
- capacity:
  - updated: 20200826
    dependent: [D1,D2]
  

Как получилось, что содержимое YAML может быть изменено, как показано ниже, в python. Оно будет инкапсулировано под тегом mainData and stage1 , stage2 и т.д. Средства для каждого «—«, stage<number value> будут увеличиваться.

 mainData:
stage1:
_engine: E1
_parameter:
- capacity:
  - updated: 20200825
    dependent: []
stage2:
_engine: E2
_parameter:
- capacity:
  - updated: 20200826
    dependent: [D1,D2]
  

Наконец, конечный поток также будет только YAML.

Комментарии:

1. Я думаю, вам придется вручную искать строку с тире и заменять ее. Затем проанализируйте результат как yaml. Вы пробовали это? Что произошло? Или вы могли бы выяснить, почему вам в первую очередь приходится иметь дело со сломанными файлами yaml.

2. Три дефиса обозначают новый документ в YAML. Смотрите yaml.info/learn/document.html

Ответ №1:

--- Является частью синтаксиса YAML. Короче говоря, это указывает на начало нового документа: https://yaml.org/spec/1.2/spec.html#YAML

Технически это фактически строка «конец директив», но если документ YAML не содержит никаких директив, то это фактически то же самое, что «начать новый документ». Это позволяет объединить несколько документов YAML вместе. С PyYAML вы можете перебирать все документы в файле с помощью yaml.load_all . Если вы хотите связать индекс «stage» с каждым документом, просто выполните:

 for stage_num, stage in enumerate(yaml.load_all(fileobj)):
   ...
  

Если вы хотите преобразовать это в один документ, вы могли бы сделать что-то вроде

 stages = {} 
for n, stage in enumerate(yaml.load_all(fileobj)):
    stages[f'stage{n}'] = stage
  

Затем дамп stages в файл YAML.

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

Комментарии:

1. Я использую версию 3.4.4 и получаю ошибку со строкой stages[f’stage {n}’] = stage как недопустимый синтаксис

2. В Python 3.4 нет f-строк.

3. Python 3.4 также довольно давно больше не поддерживается. Вы должны обновиться по крайней мере до python 3.6.

4. Я просто попытался использовать load_all вместо load и попытался распечатать yaml. Вместо печати фактического «<загрузка объекта генератора some_address всех>

5. это работает после преобразования o / p в list. например, print(список(yaml.load_all(yaml_data)))

Ответ №2:

Это должно сделать это

 import itertools

with open('/path/to/input.yml') as infile, open('/path/to/output.yml', 'w') as outfile:
    outfile.write("mainData:n")
    stage = itertools.count(1)

    for line in infile:
        if not line.startswith('---'):
            outfile.write(line)
            continue
        outfile.write(f"stage{next(stage)}:n")