yaml在PyYAML中锚定定义加载

时间:2016-05-24 12:18:25

标签: python 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}}

1 个答案:

答案 0 :(得分:3)

在从yaml.load()获得结果之前,PyYAML中的锚信息将被丢弃。这是根据PyYAML遵循的YAML 1.1规范( ...锚名称是序列化细节,一旦编写完成就被丢弃)。这在YAML 1.2规范(2009年)中没有改变。你不能在PyYAML中通过遍历result(递归)并测试哪些值可能是锚点而不需要广泛修改解析器。

在我的ruamel.yaml(YAML 1.2)中,在往返模式下,我为实际用于别名映射或序列的锚点保留了锚点和别名 (锚点别名)目前没有为标量保留,也没有&#34;未使用&#34;锚点:

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

一般地和递归地执行此操作(即,对于树中任何位置的锚点和别名)也是可能的。更新将像上面一样简单,但您需要跟踪如何删除密钥,并且这不必是映射值,它可以是序列项。