yaml.load,强制字典键为字符串

mog*_*gul 6 python yaml python-3.x

在 Python3 中,我正在加载一段 YAML。加载程序尝试猜测正确的类型,但我不太满意。我希望字典键始终是字符串。

首先要演示一段简约的 YAML,可以轻松直接粘贴到 Python 解释器中。不用说,我的现实世界数据要复杂得多。

txt = """
---
one: 1
2: two
"""
Run Code Online (Sandbox Code Playgroud)

首先是“常规”负载:

yaml.load(txt)
{2: 'two', 'one': 1}
Run Code Online (Sandbox Code Playgroud)

请注意键2如何作为数字而不是字符串加载。然后让我们尝试一些不同的东西:

yaml.load(txt, Loader=yaml.BaseLoader)
{'2': 'two', 'one': '1'}
Run Code Online (Sandbox Code Playgroud)

现在一切都变成了字符串。不幸的是还有1,作为一个值,我需要作为一个数字。

因此,我可以将键和值都强制为字符串,也可以不将其强制为字符串。

我当然可以制作一个后处理器来遍历加载的数据并将其复制到一个新变量,并将 dict 键强制为字符串,但我想它可以在 YAML 加载器中做得更优雅。

建议?

Ant*_*hon 3

您可以使用几行代码来完成此操作,更改正在构造的每个映射,以便将整数类型键即时转换为字符串。您可以子类化 SafeLoader,但是您需要注册构造函数。最简单的方法是修补映射构造函数:

import yaml

def my_construct_mapping(self, node, deep=False):
    data = self.construct_mapping_org(node, deep)
    return {(str(key) if isinstance(key, int) else key): data[key] for key in data}

yaml.SafeLoader.construct_mapping_org = yaml.SafeLoader.construct_mapping
yaml.SafeLoader.construct_mapping = my_construct_mapping


yaml_str = """\
---
one: 1
2: two
"""

data = yaml.safe_load(yaml_str)
print(data)
Run Code Online (Sandbox Code Playgroud)

这使:

{'one': 1, '2': 'two'}
Run Code Online (Sandbox Code Playgroud)

没有理由使用默认的unsafeyaml.load()即没有Loader=参数)。