彭某的技术折腾笔记

彭某的技术折腾笔记

Python 中 YAML 及 JSON 的读写

31
2023-10-08

Python 中 YAML 及 JSON 的读写

2023年10月8日

摘要

在前面的文章中,已经较为详细的介绍了 YAML 以及 JSON 两种语言。然而,在实际应用中,单独一个配置文件是没有任何作用的,和其他编程语言相结合才能相辅相成发挥强大的作用。本文就讲介绍如何用 Python 读写 YAML 及 JSON 文件。

YAML 文件

在 Python 中,有两个常用的库提供了 YAML 读写的支持:

  • PyYAML
  • ruamel.yaml

其中,ruamel.yamlPyYAML 的衍生品,做了非常多的优化和改进,本文将选用 ruamel.yaml 进行讲述。

要安装 ruamel.yaml 十分简单,使用以下两个命令之一即可:

# conda
conda install ruamel.yaml
# pip
pip install ruamel.yaml

此后,在 Python 代码中导入即可:

import ruamel.yaml as yaml

读取 YAML

ruamel.yaml 将从输入流中读取 YAML,因此,需要先使用 open 函数打开需要的 YAML 文件(以 config.yml 为例)再进行读取:

with open('config.yml', 'r') as f:
    config = yaml.load(f)

然后便可得到一个字典或是列表类型的 config 对象。

写入 YAML

如果已经有了一个字典或是列表:

config = {'cars': ['A6L', 'Panamera']}

要将其写入 YAML 文件,我们依然需要先使用 open 函数打开需要的 YAML 文件(以 dump.yml 为例)再进行读取:

with open('dump.yml', 'w') as f:
    yaml.dump(config, f)

但是得到的 YAML 文件是他的紧凑形式:

cars: [A6L, Panamera]

如果要得到我们期望的人类阅读的形式,则可以实例化一个拥有默认配置的 ruamel.yaml

with open('dump.yml', 'w') as f:
    yaml = yaml.YAML()
    yaml.dump(config, f)

这样,我们得到了:

cars:
- A6L
- Panamera

然而,此时的列表缩进有一些问题,这是不同的代码风格造成的,ruamel.yaml 相比较于 PyYAML,增加了方便的自定义选项,我们可以灵活的调整缩进:

with open('dump.yml', 'w') as f:
    yaml = yaml.YAML()
    yaml.indent(sequence=4, offset=2)
    yaml.dump(config, f)

其中,sequence 指的是数组内部的缩进,offset 指的是字典内部的缩进,此时,我们就可以完美得到想要的结果:

cars:
  - A6L
  - Panamera

如果我们需要其支持中文且不乱码,可以在 dump 之前加一行 yaml.allow_unicode = True

JSON 文件

Python 中自带了 JSON 相关的库,直接导入即可:

import json

且用法和 YAML 基本相同。

读取 JSON

Python 将从输入流中读取 JSON,因此,需要先使用 open 函数打开需要的 JSON 文件(以 config.json 为例)再进行读取:

with open('config.json', 'r') as f:
    config = json.load(f)

然后便可得到一个字典或是列表类型的 config 对象。

写入 JSON

如果已经有了一个字典或是列表:

config = {'cars': ['A6L', 'Panamera']}

要将其写入 JSON 文件,我们依然需要先使用 open 函数打开需要的 JSON 文件(以 dump.json 为例)再进行读取:

with open('dump.json', 'w') as f:
    json.dump(config, f)

但是得到的 JSON 文件是他的紧凑形式

{"cars": ["A6L", "Panamera"]}

只需要任意设置一个缩进即可让其展开:

with open('dump.json', 'w') as f:
    json.dump(config, f, indent=2)

并得到:

{
  "cars": [
    "A6L",
    "Panamera"
  ]
}

如果我们需要其支持中文且不乱码,可以在 dump 之中加一个参数 ensure_ascii=False

  • 0