假设我有一个如下所示的YAML文件:
food:
fruits:
round: apple
big: watermelon
grain: wheat
vegetable: cabbage
我希望能够在YAML文档中编写等效的python代码tasty = food['fruits']['round']
(将解析为apple)。
我可以参考一个变量,因此我可以做到
food: &FOOD
fruits:
round: apple
big: watermelon
grain: wheat
vegetable: cabbage
然后引用整个地图,例如
something: *FOOD
但是如何在YAML内部的地图地图中查找值?
答案 0 :(得分:0)
您可以为单个值创建锚点:
import yaml
def main():
yf = """
food:
fruits:
round: &FOOD apple
big: watermelon
grain: wheat
vegetable: cabbage
something: *FOOD
"""
print(yaml.load(yf))
if __name__ == '__main__':
main()
打印:
{' food':{'蔬菜':'卷心菜'' grain':'小麦',' ;水果&#39 ;:
{'大':'西瓜','围绕':' apple'}},'东西':&# 39;苹果'}
答案 1 :(得分:0)
你可以这样做:
import sys
import ruamel.yaml
yaml_str = """\
food: &FOOD
fruits:
round: apple
big: watermelon
grain: [wheat, barley, spelt]
vegetable: cabbage
something: $FOOD.fruits.big
otherthing: $.food.grain.2 # 2 -> third element
"""
def resolve(data, sep='.', initial='$'):
"""walk over tree and resolve strings that start with $
$XYZ.abc -> resolve starting at anchor XYZ
$.abc -> resolve starting at toplevel
"""
def get_anchors(d, anchors):
if isinstance(d, ruamel.yaml.comments.CommentedMap):
if d.yaml_anchor() is not None:
anchors[d.anchor.value] = d
for k in d:
get_anchors(d[k], anchors)
elif isinstance(d, ruamel.yaml.comments.CommentedSeq):
if d.yaml_anchor() is not None:
anchors[d.anchor.value] = d
for e in d:
get_anchors(e, anchors)
def resolvex(data, d, anchors, sep, initial):
if isinstance(d, ruamel.yaml.comments.CommentedMap):
for k in d:
upd, val = resolvex(data, d[k], anchors, sep, initial)
if upd:
d[k] = val
return False, None
elif isinstance(d, ruamel.yaml.comments.CommentedSeq):
for idx, e in enumerate(d):
upd, val = resolvex(data, e, anchors, sep, initial)
if upd:
d[idx] = val
return False, None
if isinstance(d, str) and d and d[0] == initial:
path = d[1:].split(sep)
dx = data if path[0] == '' else anchors.get(path[0])
while len(path) > 1:
path = path[1:]
if isinstance(dx, ruamel.yaml.comments.CommentedSeq):
dx = dx[int(path[0])]
else:
dx = dx[path[0]]
return True, dx
return False, None
anchors = {}
get_anchors(data, anchors=anchors)
resolvex(data, data, anchors, sep, initial)
data = ruamel.yaml.round_trip_load(yaml_str)
resolve(data)
ruamel.yaml.round_trip_dump(data, sys.stdout)
带输出:
food:
fruits:
round: apple
big: watermelon
grain: [wheat, barley, spelt]
vegetable: cabbage
something: watermelon
otherthing: spelt # 2 -> third element
请注意,您不能使用PyYAML执行上述操作,因为它不会保留锚名称,您必须使用ruamel.yaml(免责声明:我是该程序包的作者)。