yaml 锚定义在 PyYAML 中加载
yaml anchors definitions loading in 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}}
PyYAML 中的锚点信息在您从 yaml.load()
获得结果之前被丢弃。这是根据 PyYAML 遵循的 YAML 1.1 规范(... 锚点名称是序列化细节,一旦组合完成就会被丢弃 )。这在 YAML 1.2 规范(自 2009 年起)中没有改变。在 PyYAML 中,您不能通过遍历 result
(递归地)并测试哪些值可能是锚点来执行此操作,而无需大量修改解析器。
在我的 ruamel.yaml(即 YAML 1.2)中,我保留了锚点和别名 对于实际用于别名映射或序列的锚点 (目前不为标量保留锚别名,"unused" 锚也不保留):
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
也可以通用和递归地执行此操作(即对于树中任何位置的锚点和别名)。更新会像上面一样简单,但是你需要跟踪如何删除一个键,这不一定是一个映射值,它可以是一个序列项。
我今天也想这样做,而不是像@Anthon 建议的那样切换到 ruamel.yaml
,而是找到了 pyyaml-keep-anchors 存储库,这让我可以继续使用 pyyaml
。这是该存储库中的示例,对我来说开箱即用。
import yaml
from yaml_keep_anchors.yaml_anchor_parser import AliasResolverYamlLoader
with open('example/example.yaml', 'r') as fh:
data = yaml.load(fh, Loader=AliasResolverYamlLoader)
assert data['key_three'].anchor_name == 'anchor'
assert data['key_two']['sub_key'].anchor_name == 'anchor_val'
我正在使用 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}}
PyYAML 中的锚点信息在您从 yaml.load()
获得结果之前被丢弃。这是根据 PyYAML 遵循的 YAML 1.1 规范(... 锚点名称是序列化细节,一旦组合完成就会被丢弃 )。这在 YAML 1.2 规范(自 2009 年起)中没有改变。在 PyYAML 中,您不能通过遍历 result
(递归地)并测试哪些值可能是锚点来执行此操作,而无需大量修改解析器。
在我的 ruamel.yaml(即 YAML 1.2)中,我保留了锚点和别名 对于实际用于别名映射或序列的锚点 (目前不为标量保留锚别名,"unused" 锚也不保留):
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
也可以通用和递归地执行此操作(即对于树中任何位置的锚点和别名)。更新会像上面一样简单,但是你需要跟踪如何删除一个键,这不一定是一个映射值,它可以是一个序列项。
我今天也想这样做,而不是像@Anthon 建议的那样切换到 ruamel.yaml
,而是找到了 pyyaml-keep-anchors 存储库,这让我可以继续使用 pyyaml
。这是该存储库中的示例,对我来说开箱即用。
import yaml
from yaml_keep_anchors.yaml_anchor_parser import AliasResolverYamlLoader
with open('example/example.yaml', 'r') as fh:
data = yaml.load(fh, Loader=AliasResolverYamlLoader)
assert data['key_three'].anchor_name == 'anchor'
assert data['key_two']['sub_key'].anchor_name == 'anchor_val'