简体   繁体   English

如何从 Python 中的 YAML 文件创建树数据结构?

[英]How can I create a tree data structure from a YAML file in Python?

Suppose I have a YAML file as follows:假设我有一个 YAML 文件,如下所示:

template:
 artifacts:
  config:
   a: value1
   b: value2
  jars:
   a: value1
   b: value2
  scripts:
   a: value1
   b: value2

I would like to have it like a tree as below:我想让它像一棵树一样,如下所示:

template--
          |__artifacts__
                        |__config__
                        |          |__a__
                        |          |     |__value1
                        |          |
                        |          |__b__
                        |                |__value2
                        |__jars__ ...

How can I do that?我怎样才能做到这一点?

There are multiple parsers for YAML available for Python, but the only one supporting the latest YAML specification (1.2, released in 2009) is ruamel.yaml (disclaimer: I am the author of that package).有多种 YAML 解析器可用于 Python,但唯一支持最新 YAML 规范( 1.2,2009年发布)的解析器ruamel.yaml (免责声明:我是该包的作者)。 The other packages (PySyck, PyYAML) also do not support loading of valid YAML constructs such as sequences/mappings as mapping keys.其他包(PySyck、PyYAML)也不支持加载有效的 YAML 结构,例如序列/映射作为映射键。 ruamel.yaml can be directed to dump YAML 1.1 for those outdated packages that only support that version of the YAML specification. ruamel.yaml可以针对那些仅支持该版本 YAML 规范的过时包转储 YAML 1.1。

Nested python dict s can be used as a tree structure, with the keys a value of a node and the values that are non- dict s leaf nodes.嵌套的 python dict可以用作树结构,键是节点的值,值是非dict的叶节点。 This is the datastructure that is loaded from the mappings in your YAML file.这是从 YAML 文件中的映射加载的数据结构。

from pathlib import Path
from pprint import pprint
import ruamel.yaml

input = Path('input.yaml')
yaml = ruamel.yaml.YAML()
data = yaml.load(input)
pprint(data)

which gives:这使:

{'template': {'artifacts': {'config': {'a': 'value1',
                                       'b': 'value2'},
                            'jars': {'a': 'value1',
                                     'b': 'value2'},
                            'scripts': {'a': 'value1',
                                        'b': 'value2'}}}}

This doesn't look like your expected output, nor are dicts really a tree structure.这看起来不像您预期​​的输出,dicts 也不是真正的树结构。 You can of course walk over your data -structure and create a tree of Node s, but that is a bit backward, as you can tell the parser to directly create a Node when building the tree.您当然可以遍历您的data结构并创建一个Node树,但这有点落后,因为您可以在构建树时告诉解析器直接创建一个Node

import sys
from ruamel.yaml.constructor import SafeConstructor

class Node:
    # your node definition here
    pass


class MyConstructor(SafeConstructor):
    def construct_yaml_map(self, node):
        data = Node()
        yield data
        res = self.construct_mapping(node)
        # and update data with the parsed data

MyConstructor.add_constructor('tag:yaml.org,2002:map', 
                              MyConstructor.construct_yaml_map)


yaml = ruamel.yaml.YAML()
yaml.Constructor = MyConstructor
data = yaml.load(input)

Please note that the above automatically deals with recursive structures in your YAML file, something not as easily realised when walking over the YAML loaded in the normal way.请注意,以上内容会自动处理 YAML 文件中的递归结构,当遍历以正常方式加载的 YAML 时,这并不容易实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM