跳转至

Python 处理YAML文件

概要: 使用Python处理常见的YAML格式文件

创建时间: 2022.11.09 23:13:13

更新时间: 2022.11.10 00:08:39

YAML是什么?

YAML Ain't Markup Language™

load与dump

使用最常见的 pyyaml 包,安装方式如下

Bash
pip install pyyaml

load YAML

使用安全的 safe_load() 方法

Python
1
2
3
4
import yaml

with open('demo.yaml', 'r') as f:
    data = yaml.safe_load(f)

dump YAML

使用安全的 safe_dump() 方法

Python
1
2
3
4
5
6
import yaml

demo_data = {'a': 1, 'c': None, 'b': [1, '你好', 3], 'd': {'d1': 'x', 'd2': 'y'}}

with open('demo.yaml', 'w') as f:
    yaml.safe_dump(demo_data, f, sort_keys=False, indent=4)

关于 safe_dump() 方法

  1. safe_dump() 默认会在生成的YAML文件中对 key 排序,但由于在 Python3.7+ 后,dict 数据默认保留 key 的插入顺序,此时只需引入参数 sort_keys=False 即可保留原来的顺序
  2. safe_dump() 默认每一层缩进2个字符,如果需要调整YAML文件每一层的缩进量为4,加入参数 indent=4 即可

image.png
可以看到,调整后顺序和缩进后的文件仍然有以下问题

  1. b 字段的列表值依然不太符合大部分人书写阅读习惯
  2. 没有将 Unicode 中文字符串输出为可读性更好的 UTF-8 字符串

下面介绍增强 dump 的方法

优化dump缩进

需要我们改写一下默认的 dumper 类即可

Python
1
2
3
4
5
6
7
class BetterDumper(yaml.Dumper):
    def increase_indent(self, flow=False, indentless=False):
        return super(BetterDumper, self).increase_indent(flow, False)


with open('demo_better.yaml', 'w') as f:
    yaml.dump(demo_data, f, sort_keys=False, Dumper=BetterDumper)
image.png

优化dump字符

dump() 或者 safe_dump() 函数中加入参数 allow_unicode=True 即可

Python
with open('demo_better.yaml', 'w') as f:
    yaml.dump(demo_data, f, sort_keys=False, indent=2, Dumper=BetterDumper, allow_unicode=True)
image.png

其他YAML包

如果需要最大程度保留输入数据的格式,推荐 ruamel.yaml ,它专注于 YAML 1.2 格式的支持,是来自 pyyaml 包的一个分支。安装如下

Bash
pip install ruamel.yaml
示例用法,无需其他参数,可以直接输出可读的中文字符,并保留原字典顺序
Python
1
2
3
4
5
6
7
8
import ruamel.yaml

yaml = ruamel.yaml.YAML()

demo_data = {'a': 1, 'c': None, 'b': [1, '你好', 3], 'd': {'d1': 'x', 'd2': 'y'}}

with open('demo_ruamel.yaml', 'w') as f:
    yaml.dump(demo_data, f)
image.png
此外,如果从字符串进行 dump ,那么使用 ruamel.yaml 生成的文件,注释也可以一并保留
Python
str_data = """
a: 12  # A
b:
  b1: True
  b2: hello world  # greet
  b3: False
"""

map_data = yaml.load(str_data)

with open('demo_ruamel_comment.yaml', 'w') as f:
    yaml.dump(map_data, f)
image.png

如果需要对YAML格式的严格检查,可以使用 crdoconnor/strictyaml: Type-safe YAML parser and validator. 这个包,不再赘述。

参考