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