загрузка определений якорей yaml в PyYAML

Я использую PyYAML. Есть ли способ определить привязку YAML таким образом, чтобы она не была частью структуры данных, загружаемой yaml.load (я могу удалить «wifi_parm» из словаря, но ищу более разумный способ)?

example.yaml:

wifi_parm: &wifi_params
  ssid: 1
  key: 2
test1:
  name: connectivity
  <<: *wifi_params
test2:
  name: connectivity_5ghz
  <<: *wifi_params

load_example.py:

import yaml
import pprint

with open('aaa.yaml', 'r') as f:
    result = yaml.load(f)
pprint.pprint(result)

печатает:

{'test1': {'key': 2, 'name': 'connectivity', 'ssid': 1},
 'test2': {'key': 2, 'name': 'connectivity_5ghz', 'ssid': 1},
 'wifi_parm': {'key': 2, 'ssid': 1}}

Я нуждаюсь:

{'test1': {'key': 2, 'name': 'connectivity', 'ssid': 1},
 'test2': {'key': 2, 'name': 'connectivity_5ghz', 'ssid': 1}}

person adi    schedule 24.05.2016    source источник


Ответы (1)


Информация о привязке в PyYAML отбрасывается до того, как вы получите результат от yaml.load(). Это соответствует спецификации YAML 1.1, которой следует PyYAML (... привязка имена являются деталью сериализации и отбрасываются после завершения создания). Это не изменилось в спецификации YAML 1.2 (с 2009 г.). Вы не можете сделать это в PyYAML, пройдя по вашему result (рекурсивно) и проверив, какие значения могут быть якорями, без значительного изменения парсера.

В моем ruamel.yaml (который является YAML 1.2) в режиме приема-передачи, Я сохраняю привязки и псевдонимы для привязок, которые фактически используются для сопоставлений псевдонимов или последовательностей (псевдонимы привязок в настоящее время не сохраняются для скаляров и не являются «неиспользуемыми» привязками):

import ruamel.yaml

with open('aaa.yaml') as f:
    result = ruamel.yaml.round_trip_load(f)

ruamel.yaml.round_trip_dump(result, sys.stdout)

дает:

wifi_parm: &wifi_params
  ssid: 1
  key: 2
test1:
  <<: *wifi_params
  name: connectivity
test2:
  <<: *wifi_params
  name: connectivity_5ghz

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

import ruamel.yaml
from ruamel.yaml.comments import merge_attrib

with open('aaa.yaml') as f:
    result = ruamel.yaml.round_trip_load(f)

keys_to_delete = []
for k in result:
    v = result[k]
    if v.yaml_anchor():
        keys_to_delete.append(k)
    for merge_data in v.merge:  # update the dict with the merge data 
        v.update(merge_data[1])
        delattr(v, merge_attrib)
for k in keys_to_delete:
    del result[k]

ruamel.yaml.round_trip_dump(result, sys.stdout)

дает:

test1:
  name: connectivity
  ssid: 1
  key: 2
test2:
  name: connectivity_5ghz
  ssid: 1
  key: 2

делать это в общем и рекурсивно (то есть для якорей и псевдонимов, которые находятся в любом месте дерева) также возможно. Обновление будет таким же простым, как и выше, но вам нужно будет отслеживать, как удалить ключ, и это не обязательно должно быть значение сопоставления, это может быть элемент последовательности.

person Anthon    schedule 24.05.2016