【问题标题】:How can I create a tree data structure from a YAML file in Python?如何从 Python 中的 YAML 文件创建树数据结构?
【发布时间】:2019-04-07 23:28:44
【问题描述】:

假设我有一个如下的 YAML 文件:

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

我希望它像一棵树,如下所示:

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

我该怎么做?

【问题讨论】:

    标签: python python-3.x algorithm yaml


    【解决方案1】:

    有多个 YAML 解析器可用于 Python,但唯一的 一个支持最新的 YAML 规范(1.2,2009 年发布) 是ruamel.yaml(免责声明: 我是那个包的作者)。其他包(PySyck、PyYAML) 也不支持加载有效的 YAML 结构,例如 序列/映射作为映射键。 ruamel.yaml 可以定向到 转储 YAML 1.1 用于那些仅支持的过时软件包 YAML 规范的版本。

    嵌套pythondicts 可以作为树形结构使用,键为a 节点的值和非dicts 叶节点的值。这是 从 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)
    

    给出:

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

    这看起来不像您预期​​的输出,dicts 也不是真正的树结构。 你当然可以走过你的data-结构并创建一个Nodes的树,但是 这有点落后,因为您可以告诉解析器直接创建一个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)
    

    请注意,以上内容会自动处理 YAML 文件中的递归结构, 遍历以正常方式加载的 YAML 时不容易实现的东西。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-26
      • 1970-01-01
      • 1970-01-01
      • 2015-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多