配置 ruamel.yaml 以允许重复键

2023-12-10

我正在尝试使用ruamel.yaml用于处理包含重复键的 Yaml 文档的库。在这种情况下,重复的键恰好是合并键<<:.

这是 yaml 文件,dupe.yml:

foo: &ref1
  a: 1

bar: &ref2
  b: 2

baz:
  <<: *ref1
  <<: *ref2
  c: 3

这是我的脚本:

import ruamel.yaml

yml = ruamel.yaml.YAML()
yml.allow_duplicate_keys = True
doc = yml.load(open('dupe.yml'))

assert doc['baz']['a'] == 1
assert doc['baz']['b'] == 2
assert doc['baz']['c'] == 3

运行时,会引发此错误:

Traceback (most recent call last):
  File "rua.py", line 5, in <module>
    yml.load(open('dupe.yml'))
  File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/main.py", line 331, in load
    return constructor.get_single_data()
  File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 111, in get_single_data
    return self.construct_document(node)
  File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 121, in construct_document
    for _dummy in generator:
  File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 1543, in construct_yaml_map
    self.construct_mapping(node, data, deep=True)
  File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 1448, in construct_mapping
    value = self.construct_object(value_node, deep=deep)
  File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 174, in construct_object
    for _dummy in generator:
  File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 1543, in construct_yaml_map
    self.construct_mapping(node, data, deep=True)
  File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 1399, in construct_mapping
    merge_map = self.flatten_mapping(node)
  File "/usr/local/lib/python3.7/site-packages/ruamel/yaml/constructor.py", line 1350, in flatten_mapping
    raise DuplicateKeyError(*args)
ruamel.yaml.constructor.DuplicateKeyError: while constructing a mapping
  in "dupe.yml", line 8, column 3
found duplicate key "<<"
  in "dupe.yml", line 9, column 3

To suppress this check see:
   http://yaml.readthedocs.io/en/latest/api.html#duplicate-keys

Duplicate keys will become an error in future releases, and are errors
by default when using the new API.

我怎样才能让 ruamel 读取这个文件而不会出现错误?文档说allow_duplicate_keys = True将使加载程序容忍重复的密钥,但它似乎不起作用。

我正在使用 Python 3.7 和 ruamel.yaml 0.15.90。


That

yaml.allow_duplicate_keys = True

仅适用于 0.15.91 之前版本中的非合并键。

在 0.15.91+ 中,这是有效的,并且合并键假定该键的第一个实例化的值(与非合并键一样),这意味着它的工作方式就像您编写的一样:

baz:
  <<: *ref1
  c: 3

and not就好像你写过:

baz:
  <<: [*ref1, *ref2]
  c: 3

如果您需要,则必须对处理合并键的展平例程进行猴子修补(这会影响使用双合并键加载所有以下 YAML 文件):

import sys
import ruamel.yaml

yaml_str = """\
foo: &ref1
  a: 1

bar: &ref2
  b: 2

baz:
  <<: *ref1
  <<: *ref2
  c: 3

"""

def my_flatten_mapping(self, node):

    def constructed(value_node):
        # type: (Any) -> Any
        # If the contents of a merge are defined within the
        # merge marker, then they won't have been constructed
        # yet. But if they were already constructed, we need to use
        # the existing object.
        if value_node in self.constructed_objects:
            value = self.constructed_objects[value_node]
        else:
            value = self.construct_object(value_node, deep=False)
        return value

    merge_map_list = []
    index = 0
    while index < len(node.value):
        key_node, value_node = node.value[index]
        if key_node.tag == u'tag:yaml.org,2002:merge':
            if merge_map_list and not self.allow_duplicate_keys:  # double << key
                args = [
                    'while constructing a mapping',
                    node.start_mark,
                    'found duplicate key "{}"'.format(key_node.value),
                    key_node.start_mark,
                    """
                    To suppress this check see:
                       http://yaml.readthedocs.io/en/latest/api.html#duplicate-keys
                    """,
                    """\
                    Duplicate keys will become an error in future releases, and are errors
                    by default when using the new API.
                    """,
                ]
                if self.allow_duplicate_keys is None:
                    warnings.warn(DuplicateKeyFutureWarning(*args))
                else:
                    raise DuplicateKeyError(*args)
            del node.value[index]
            # if key/values from later merge keys have preference you need
            # to insert value_node(s) at the beginning of merge_map_list
            # instead of appending
            if isinstance(value_node, ruamel.yaml.nodes.MappingNode):
                merge_map_list.append((index, constructed(value_node)))
            elif isinstance(value_node, ruamel.yaml.nodes.SequenceNode):
                for subnode in value_node.value:
                    if not isinstance(subnode, ruamel.yaml.nodes.MappingNode):
                        raise ruamel.yaml.constructor.ConstructorError(
                            'while constructing a mapping',
                            node.start_mark,
                            'expected a mapping for merging, but found %s' % subnode.id,
                            subnode.start_mark,
                        )
                    merge_map_list.append((index, constructed(subnode)))
            else:
                raise ConstructorError(
                    'while constructing a mapping',
                    node.start_mark,
                    'expected a mapping or list of mappings for merging, '
                    'but found %s' % value_node.id,
                    value_node.start_mark,
                )
        elif key_node.tag == u'tag:yaml.org,2002:value':
            key_node.tag = u'tag:yaml.org,2002:str'
            index += 1
        else:
            index += 1
    return merge_map_list

ruamel.yaml.constructor.RoundTripConstructor.flatten_mapping = my_flatten_mapping

yaml = ruamel.yaml.YAML()
yaml.allow_duplicate_keys = True
data = yaml.load(yaml_str)
for k in data['baz']:
    print(k, '>', data['baz'][k])

上式给出:

c > 3
a > 1
b > 2
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

配置 ruamel.yaml 以允许重复键 的相关文章

随机推荐

  • rvest 中的 html 与 XML 中的 htmlParse

    如下面的代码所示 html in rvest封装用途htmlParse from XML包裹 html function x encoding NULL parse x XML htmlParse encoding encoding
  • SDL_PollEvent 似乎阻止窗口表面更新

    我目前正在浏览 SDL2 的 Lazy Foo 教程 我在 Linux 机器上执行此操作 并且遇到了某种错误 其中包含SDL PollEvent在我的主循环中似乎可以防止SDL UpdateWindowSurface从实际更新来看 如果我离
  • Windows 服务 - 如何使任务在多个特定时间运行?

    我有一个 Windows 服务正在运行 目前该任务在每天晚上 7 点运行 让它运行的最佳方式是什么 例如上午 9 45 上午 11 45 下午 2 点 下午 3 45 下午 5 点和下午 5 45 我知道我可以安排任务来运行该功能 但我想知
  • 不同语言中的静态

    我听说不同语言的关键字含义存在差异static 但我还没有找到一个很好的列表来巩固这些差异 这是我所知道的含义static in C 对于函数内的局部静态变量 变量在启动时初始化 并且值在函数调用期间保存 静态数据成员在类的所有实例之间共享
  • 如何加密Lua代码[关闭]

    Closed 这个问题需要细节或清晰度 目前不接受答案 我想保护我的项目中的 Lua 代码 我正在使用 Corona SDK 我看到一些 lua 文件像这样被混淆了 https github com ChartBoost corona sd
  • Python 函数列表

    是否可以创建一个可以单独访问的函数列表 例如 e 0 def a global e e 1 def b global e e 2 def c global e e 3 l a b c l 2 print e l 0 print e Outp
  • 计算 awk 中文件中 $2,$3 之间的日期差

    我需要你的帮助 仅包含日期的文件 file txt P1 2013 jul 9 2013 jul 14 P2 2013 jul 14 2013 jul 6 P3 2013 jul 7 2013 jul 5 像这样显示输出 P1 2013 j
  • 在 Excel 中将具有多行数据的列转换为具有多列的行。

    我的数据按多行列组织 需要将其转换为多列行以进行数据分析 例如 ID Date of entry Location Data1 Data2 1 20101030 1 a b 1 20101030 2 c d 1 20101125 1 w v
  • 为什么 C++ 没有 ~= 和 != 运算符? [关闭]

    Closed 这个问题需要细节或清晰度 目前不接受答案 这与标题中描述的差不多 为什么 C 没有 和 运算符 它们偶尔会很有用 特别是在探索重载可能性时 另一种选择a a and a a表述不必要地冗长 Taking 作为 通用 运算符 类
  • 如果套接字必须已经绑定到它,为什么 DatagramSocketImpl joinGroup 方法需要一个 NetworkInterface?

    只是好奇 这是多余的吗 您还没有绑定您要使用的网络吗 也许这是您绑定到 0 0 0 0 并且现在只想侦听来自接口 X 的多播数据包的情况 如果您绑定到 INADDR ANY 这是正常情况 则加入组 IGMP 消息将通过路由表显示提供到多播地
  • 从模态返回数据时 ng-grid 中的范围混乱

    这是笨蛋 http plnkr co edit aqLnno p preview 我有一份人员名单 scope persons 显示在 ng grid 中 每行都有一个编辑按钮 当用户单击按钮 ng click edit row 见下面的代
  • 基于浏览器语言的 404 页面与 mod_rewrite 如何

    我试图通过评估客户端 HTTP Accept Language 标头来纯粹基于 Apache mod rewrite 规则生成语言相关的 404 还有其他错误 页面 我已经设法使用以下规则显示正确的页面 默认英文 RewriteEngine
  • JOptionPane.showMessageDialog 截断 JTextArea 消息

    我的 Java GUI 应用程序需要快速向最终用户显示一些文本 因此JOptionPane实用方法似乎很合适 此外 文本必须是可选择的 用于复制和粘贴 并且可能有点长 约 100 个单词 因此它必须很好地适合窗口 屏幕外没有文本 理想情况下
  • 将自定义属性添加到客户端实体类

    我需要向实体框架类添加自定义属性 但是当我这样做时 我收到 为类型 XXX 指定的属性名称 XXX 无效 错误 我可以为该属性提供一些属性 以便它被忽略并且不映射到任何东西吗 编辑 如果我添加自定义属性 按照下面 Martin 的示例 则以
  • Internet Explorer 错误:SCRIPT5009:ArrayBuffer 未定义

    我在 Internet Explorer 9 中收到错误 但在其他浏览器上不会出现该错误 它是 SCRIPT5009 ArrayBuffer 未定义 我的代码如下 var rawLength raw length var array new
  • 使用 REST 和 C# 实现 Google 音译 API,面临 unicode 和解析问题

    我一直在尝试使用 RESTful 方法来使用 Google Transliterate API 因为通过服务器端语言 此处为 C 很容易做到这一点 所以 我遇到了这种 URL 格式 它返回以下格式的 JSON ew bharat hws e
  • 如何自动停止 jQuery 验证表单验证?

    我有一个文本框 在其中创建了一个 onblur 脚本 该脚本接受输入并将其转换为日期 我正在使用 jQuery validate plugin 来验证输入 但问题是用户的输入通常在我解析之后才有效 这使得 jQuery 验证所做的自动验证既
  • Graphhopper 返回“未找到”

    我正在测试 graphhopper 有几天了 但是有一个奇怪的问题 当位置对于下一个街道 graphhopper 来说太远时 返回错误 未找到 奇怪的是它可以在 graphhopper demo server 上运行 我尝试了阿尔卑斯山 欧
  • PHP读取受保护的文件

    我在子域 a 上有一个 xml 文件 在子域 b 上有一个 php 脚本 我想通过 PHP 读取并使用 XML 文件中的数据 这就是问题所在 该文件使用 HTTP 身份验证进行保护 如何让PHP登录并读取文件内容 The 网址包装器支持表单
  • 配置 ruamel.yaml 以允许重复键

    我正在尝试使用ruamel yaml用于处理包含重复键的 Yaml 文档的库 在这种情况下 重复的键恰好是合并键 lt lt 这是 yaml 文件 dupe yml foo ref1 a 1 bar ref2 b 2 baz lt lt r