Сохраните блок из файла YAML и добавьте его в существующий файл YAML с помощью Python.

У меня есть большая часть кода, где я читаю каждый файл и выгружаю его в новый файл. Мой следующий шаг — сохранить car1 (от мамы, файл2) и добавить его в блок папы как car2, file1).

------
File 1
------
dad:
  car1:
    model: [toyota-venza]
    awd: true
    option:
      nav:
        backup_camera: true
        version: 1.35 
    mileage: 54,025
    year: 2000
age:
  ...

------
File 2
------
mom:
  car1:
    model: [toyota-camry]
    awd: false
    option:
      nav:
        backup_camera: false
        version: []
    mileage: 20,241
    year: 2013
age:
  ...

Где новый файл будет выглядеть так... содержащий car1 и car2 для папы.

dad:
  car1:
    model: [toyota-venza]
    awd: true
    option:
      nav:
        backup_camera: true
          version: 1.35 
    mileage: 54,025
    year: 2000
  car2:
    model: [toyota-camry]
    awd: false
    option:
      nav:
        backup_camera: false
          version: []
    mileage: 20,241
    year: 2013

person user3203920    schedule 31.08.2015    source источник
comment
По каким критериям вы подразумеваете соответствие car2? Всегда ли это первый ключ первого ключа? Ваш входной файл не является действительным YAML, ваш version имеет вводящий в заблуждение отступ   -  person Finwood    schedule 31.08.2015
comment
Для автомобиля 2, я думаю, мне нужен блок, содержащий автомобиль 2. Да, это должен быть первый ключ первого ключа. Извините за плохой отступ...   -  person user3203920    schedule 31.08.2015
comment
Ваши примеры недействительны для YAML. Ваш version имеет отступ в два пробела относительно родственного ключа backup_camera, что недопустимо.   -  person Anthon    schedule 31.08.2015


Ответы (1)


Предполагая, что вы нашли информацию об автомобиле с помощью ключа 'car1', вы можете искать сопоставление верхнего уровня для значения с этим ключом:

import ruamel.yaml as yaml
from ruamel.yaml.comments import CommentedMap
import glob

dad = CommentedMap()
dad['dad'] = d = CommentedMap()

for idx, file_name in enumerate(sorted(glob.glob('car*.yaml'))):
    data = yaml.load(open(file_name), Loader=yaml.RoundTripLoader)
    for k in data:
        if 'car1' in data[k]:
            new_key = 'car{0}'.format(idx+1)
            d[new_key] = data[k]['car1']
            d.yaml_add_eol_comment('# from {0} in {1}'.format(k, file_name),
                                   key=new_key, column=30)

print(yaml.dump(dad, Dumper=yaml.RoundTripDumper))

дает тебе:

dad:
  car1:                       # from dad in car1.yaml
    model: [toyota-venza]
    awd: true
    option:
      nav:
        backup_camera: true
        version: 1.35
    mileage: 54,025
    year: 2000
  car2:                       # from mom in car2.yaml
    model: [toyota-camry]
    awd: false
    option:
      nav:
        backup_camera: false
        version: []
    mileage: 20,241
    year: 2013

Предположим, что данные в файлах car1.yaml и car2.yaml. Я использовал здесь ruamel.yaml¹, чтобы использовать упорядоченные карты, к которым вы прикрепляете комментарии.

Вы можете сделать это с помощью PyYAML, но вы потеряете гарантированный порядок и комментарии:

import yaml
import glob

dad = dict()
dad['dad'] = d = dict()

for idx, file_name in enumerate(sorted(glob.glob('car*.yaml'))):
    data = yaml.load(open(file_name), Loader=yaml.SafeLoader)
    for k in data:
        if 'car1' in data[k]:
            new_key = 'car{0}'.format(idx+1)
            d[new_key] = data[k]['car1']

print(yaml.dump(dad, Dumper=yaml.SafeDumper))

¹ Это было сделано с использованием ruamel.yaml, автором которого я являюсь.

person Anthon    schedule 31.08.2015
comment
папа = CommentedMap() папа['папа'] = d = CommentedMap() - person user3203920; 31.08.2015
comment
извините, я не могу установить пакет, потому что у меня Centos 5.1. Что эквивалентно папе и д, если я использовал pyyaml? - person user3203920; 31.08.2015
comment
@user3203920 user3203920 как ты установил? Используете pip install ruamel.yaml? Я сделаю пониженную версию PyYAML и отредактирую пост. - person Anthon; 31.08.2015