yaml.load,强制dict键到字符串

时间:2018-04-26 14:30:02

标签: python python-3.x yaml

在Python3中我正在加载一块YAML。加载器试图猜测正确的类型,但我不太满意。我希望dict键永远是字符串。

首先是一个简约的YAML片段来演示,很容易直接粘贴到你的python解释器中。不用说,我的现实世界数据要复杂得多。

txt = """
---
one: 1
2: two
"""

首先"常规"负载:

yaml.load(txt)
{2: 'two', 'one': 1}

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

yaml.load(txt, Loader=yaml.BaseLoader)
{'2': 'two', 'one': '1'}

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

所以我既可以将键和值强制为字符串,也可以不使用。

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

建议?

2 个答案:

答案 0 :(得分:2)

您可以使用几行代码执行此操作,更改正在构造的每个映射,以便将整数类型键动态转换为字符串。您可以继承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)

给出:

{'one': 1, '2': 'two'}

没有理由使用默认的不安全yaml.load()(即没有Loader=参数)。

答案 1 :(得分:1)

围绕yaml库中的代码,看起来像制作一个自定义加载器一次完成所有这将是一项相当大的任务。除非你有一个特别大的yaml文件,你正在尝试处理并且确实需要避免第二次传递,所以只需使用字典理解进行后处理可能是最简单的:

In [15]: {str(k): v for k, v in yaml.load(txt).items()}
Out[15]: {'2': 'two', 'one': 1}