您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

使用Python在YAML中获取重复密钥

使用Python在YAML中获取重复密钥

PyYAML只会覆盖第一个条目,ruamel.yaml¹将为DuplicateKeyFutureWarningif(如果与旧版API一起使用),并DuplicateKeyError为新API提出一个

如果您不想Constructor为所有类型创建一个全数,SafeConstructor则应覆盖其中的映射构造函数来完成此工作:

    import sys
    from ruamel.yaml import YAML
    from ruamel.yaml.constructor import SafeConstructor

    yaml_str = """\
    build:
      step: 'step1'

    build:
      step: 'step2'
    """


    def construct_yaml_map(self, node):
        # test if there are duplicate node keys
        data = []
        yield data
        for key_node, value_node in node.value:
            key = self.construct_object(key_node, deep=True)
            val = self.construct_object(value_node, deep=True)
            data.append((key, val))


    SafeConstructor.add_constructor(u'tag:yaml.org,2002:map', construct_yaml_map)
    yaml = YAML(typ='safe')
    data = yaml.load(yaml_str)
    print(data)

这使:

[('build', [('step', 'step1')]), ('build', [('step', 'step2')])]

但是,似乎没有必要将step: 'step1'其列入列表。以下仅在有重复项的情况下创建列表(可以通过缓存的结果进行优化,如有必要self.construct_object(key_node, deep=True)):

    def construct_yaml_map(self, node):
        # test if there are duplicate node keys
        keys = set()
        for key_node, value_node in node.value:
            key = self.construct_object(key_node, deep=True)
            if key in keys:
                break
            keys.add(key)
        else:
            data = {}  # type: Dict[Any, Any]
            yield data
            value = self.construct_mapping(node)
            data.update(value)
            return
        data = []
        yield data
        for key_node, value_node in node.value:
            key = self.construct_object(key_node, deep=True)
            val = self.construct_object(value_node, deep=True)
            data.append((key, val))

这使:

[('build', {'step': 'step1'}), ('build', {'step': 'step2'})]

一些要点:

yaml_out = YAML(typ='safe')

yaml_out.dump(data, sys.stdout)

给出(与第一个construct_yaml_map):

    - - build
  - - [step, step1]
- - build
  - - [step, step2]
        from pathlib import Path  # or: from ruamel.std.pathlib import Path
    yaml = YAML(typ='safe')
    yaml.load(Path('file.yml')

¹免责声明:我是该软件包的作者。

python 2022/1/1 18:38:31 有495人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶