Python YAML 解析器

2025 年 1 月 12 日 | 11 分钟阅读

在本教程中,我们将学习如何使用 Python 读取、写入或对 YAML 文件执行各种操作。我们将讨论 YAML 文件格式、其用法以及如何使用 Python 对其进行操作。

让我们简单介绍一下 YAML。

什么是 YAML?

YAML,即 **Yet Another Markup Language** 的缩写,是一种人类可读的数据序列化格式,常用于配置文件和编程语言之间的数据交换。它强调简单性,易于读写,使用缩进来表示数据结构。与 XML 或 JSON 等格式不同,YAML 使用最少的语法,避免括号或逗号,并依赖于空白字符。它支持复杂的数据类型,如映射(字典)、列表和标量值。YAML 广泛应用于 DevOps、Ansible 等配置管理工具以及 Kubernetes 等云环境中的配置管理。

YAML 支持三种数据类型——标量(字符串、整数和浮点数)、列表和关联数组。

YAML 文件以 .yaml 或 .yml 扩展名保存。我们可以使用 # 符号在 YAML 中添加注释。每个子项前面都有一个连字符。值可以使用缩进进行嵌套。

YAML 的优点

YAML 的一些重要优点如下。

  • **所有编程语言都支持 YAML** - 我们只需用一种语言编写 YAML,几乎所有编程语言都可以使用它,无需任何修改。
  • **对象序列化** - 我们可以序列化 YAML 数据格式。
  • **易于阅读** - 没有硬性规定来创建 YAML 文件。简单的缩进用于定义单个块和文档。

在进一步开始之前,我们假设您对 Python 有基本的了解或具有 Python 编程语言的初级编程经验。

PyYAML 模块

PyYAML 是一个 Python 模块,它提供了一系列方法来对 YAML 文件执行多种操作。我们可以轻松地将 YAML 文件转换为字典并读取其内容。借助 YAML 模块,我们可以读取复杂的 YAML 配置文件、序列化和持久化 YAML 数据。

要使用 PyYAML,我们需要将其安装到我们的系统中。以下是 PyYAML 模块的安装步骤。

安装 PyYAML

我们可以使用以下方法安装它。

  • 使用 pip 命令安装
  • 通过源代码安装

使用 pip 命令

我们可以使用 pip 命令安装它。在终端中输入以下命令以安装 PyYAML 模块。

通过源代码安装

如果使用 pip 命令遇到错误,我们可以使用替代安装方式。请遵循以下说明。

  • 打开 PyYAML Github 存储库,点击代码部分并下载 ZIP 文件。
  • 解压下载的 zip 文件。
  • 现在打开终端并更改到 zip 文件解压的目录。
  • 现在运行 python setup.py 命令并按回车键。它将在您的机器上安装 PyYAML 模块。

读取 YAML 文件

首先,我们创建一个名为 **sample.yaml** 的新 YAML 文件,该文件将用于使用 PyYAML 模块读取。

sample.py

**yaml.load()** 方法用于读取 YAML 文件。此方法解析 YAML 对象并将其转换为 Python 字典,以便我们可以轻松读取内容。此过程称为将 YAML 文件反序列化为 Python。

load() 方法接受一个参数,该参数可以是字节字符串、打开的二进制文件对象、Unicode 字符串或打开的 YAML 文件对象。

如果我们将文件或字节字符串作为参数传递,它应该以 utf-8、utf-16-be 或 utf-16-le 编码。

让我们理解下面的例子。

示例 -

输出

[{'UserName': 'Antonio', 'Password': 'fire123 *', 'phone': 9879098, 'Skills': '-Python -SQL -Django -Rest Framework -JavaScript'}]

解释 -

在上面的代码中,我们导入了 yaml 及其 Loader 来读取 YAML 文件。**load()** 函数附带四种类型的 Loader。

  • **SafeLoader** - 我们在上面的示例中使用了这个 Loader。它安全地加载 YAML 的子集。它主要用于输入来自不受信任的来源时。
  • **BaseLoader** - 它将所有基本的 YAML 标量作为字符串加载。
  • **FullLoader** - 它的工作方式与 BaseLoader 相同,但避免了任意代码执行。如果输入来自不受信任的来源,它可能会构成安全威胁。
  • **UnsafeLoader** - 它是推荐用于不受信任源输入的加载器,通常用于向后兼容。

**load()** 方法返回了生成器对象,我们将其类型转换为列表并可以访问任何元素。

我们还可以以字典的形式获取相同的值。让我们理解以下示例。

我们还可以以字典的形式获取 yaml 值。让我们理解以下示例。

示例 - 2

输出

{'UserName': 'Antonio', 'Password': 'fire123 *', 'phone': 9879098, 'Skills': '-Python -SQL -Django -Rest Framework -JavaScript'}

我们将标量参数 SafeLoader 更改为 **FullLoader**,它将 YAML 数据转换为字典。此加载器的优点是,我们无需将加载的数据类型转换为列表。

读取多个 YAML 文档

我们可以使用 **yaml.load_all()** 方法读取多个 YAML 文档。单个 YAML 文件可以有多个文档。下面是单个文件中有多个文档的示例。

sample.yaml

文档以三个破折号 (---) 开头,以三个点 (…) 结尾。让我们理解以下示例。

示例 -

输出

[{'UserName': 'Antonio', 'Password': 'fire123 *', 'phone': 9879098, 'Skills': '-Python -SQL -Django -Rest Framework -JavaScript'}, {'UserName': 'Maino', 'Password': 'fire123 *', 'phone': 9879098, 'Skills': '-Python -SQL -Django -Rest Framework -JavaScript'}, {'UserName': 'George', 'Password': 'fire123 *', 'phone': 9879098, 'Skills': '-Python -SQL -Django -Rest Framework -JavaScript'}]

解释 -

**load()** 方法返回了生成器对象,我们将其类型转换为列表,以便可以访问任何元素。在前面的示例中,我们学习了如何读取 YAML 文件。现在我们将学习如何将数据转储到 YAML 文件中。

使用 PyYAML 模块写入 YAML 文件

将 Python 数据写入 YAML 称为序列化。要将数据转储到 yaml 文件中,我们将使用 **yaml.dump()** 方法。让我们理解以下示例。

示例 -

输出

Password: Xavier@123
  Phone: 345464
  Skills:
  - Python
  - SQL
  - Django
  - Rest Framework
  - JavaScript
  User: Zoey
- name: Zaara
  occupation: Dentist

解释 -

**dump()** 方法将 Python 对象转换为 YAML 格式并将其写入 YAML 文件。我们在上面的示例中也做了同样的事情。**dump()** 方法接受两个参数——数据和流。

数据参数表示将转换为 YAML 流的 Python 对象。第二个参数是一个文件,它必须是文本文件或二进制文件。YAML 流数据将被写入给定文件名;否则,**dump()** 将返回生成的文档。

让我们理解将 Python 数据写入文件的示例。

示例 - 2

输出

NewDetails.yaml

- User: Zoey
  Password: Xavier@123
  Phone: 345464
  Skills:
  - Python
  - SQL
  - Django
  - Rest Framework
  - JavaScript
- name: Zaara
  occupation: Dentist

说明

在上面的示例中,首先,我们定义了要写入文件的 Python 字典。然后,我们以写入模式打开了 new details.YAML 文件。我们使用了 dump() 方法并传入了 Python 字典对象以及另外两个标签。这些标签是:

  • **default_flow_style** - 用于以适当的缩进显示嵌套块的内容。默认情况下,它为 **True**。如果我们将其值设置为 false,并且嵌套列表中的值以流式样式显示,它将以适当的缩进显示块式样式的内容。
  • **sort_keys** - 用于按字母顺序对键进行排序。默认情况下,它为 **True**。如果我们将其值设置为 false,它将保持插入顺序。

转储多个 YAML 文档

**yaml.dump_all()** 方法用于将多个 YAML 文档转储到单个流。此方法接受一个列表或生成器,用于生成要序列化为 YAML 文档的 Python 对象,以及一个可选的第二个参数作为打开的文件。

让我们理解下面的例子。

示例 -

输出

Using dump() method
- Password: Xavier@123
  Phone: 345464
  Skills:
  - Python
  - SQL
  - Django
  - Rest Framework
  - JavaScript
  User: Zoey
- name: Zaara
  occupation: Dentist

Using dump_all() method
Password: Xavier@123
Phone: 345464
Skills:
- Python
- SQL
- Django
- Rest Framework
- JavaScript
User: Zoey
---
name: Zaara
occupation: Dentist

Python YAML 排序键

sort_keys 是一个可选标签,用于将 Python 数据转储到文件中。如果将其设置为 True,它将按字母顺序对 YAML 文档的所有键进行排序。让我们理解以下示例。

示例 -

输出

Before Sorting......

{'UserId': '09123', 'UserName': 'Antonio', 'Password': 'fire123 *', 'Phone': 9879098, 'Email': 'antonio@test.com', 'Skills': '-Python -SQL -Django -Rest Framework -JavaScript', 'JobRole': 'Software Developer'}

--------------------
After Sorting......

Email: antonio@test.com
JobRole: Software Developer
Password: fire123 *
Phone: 9879098
Skills: -Python -SQL -Django -Rest Framework -JavaScript
UserId: 09123
UserName: Antonio

格式化 YAML 文件

PyYaml 模块提供了在写入 YAML 文档时格式化 YAML 文件的功能。dump() 方法支持各种格式化参数。以下是格式化参数。

参数 -

  • **indent** - 它有助于设置首选缩进。
  • **width** - 它有助于设置首选宽度。
  • **canonical=True** - 它强制标量和集合使用首选样式。

让我们理解以下示例 -

示例 -

输出

Password: fire123 *
Skills: -Python -SQL -Django -Rest Framework -JavaScript
UserName: Antonio
phone: 9879098

自定义 Python 类 YAML 可序列化

我们可以创建自定义 Python 类,将 YAML 转换为自定义 Python 对象而不是列表或内置类型。

让我们理解以下示例 -

示例 -

输出

Jessa queue@123

PyYAML 的自定义标签

我们可以根据应用程序需求创建自定义标签,并在解析 YAML 文件时为自定义标签分配默认值。为此,它涉及以下几个步骤。

  • 第一步,我们定义一个构造函数,它接受加载器和 YAML 节点。
  • 我们在创建的构造函数中调用 **constuct_mapping()** 方法,它将返回与 YAML 节点对应的 Python 字典。它将返回带有字典的构造函数。
  • 返回的构造函数将被传递给 **add_constructor()**,它将 YAML 表示图转换为本机 Python 对象。构造函数接受 Loader 实例和一个节点,并返回 Python 对象。
  • 现在,load() 方法可以接受 add_constructor() 中定义的相同自定义标签所需的许多字段。没有值的字段将被分配 __init__() 方法中定义的默认值。

让我们理解下面的例子。

示例 -

输出

["Custom Tags { user = 'Sam' password = 'test@123' phone = 1100 }", "Custom Tags { user = 'Gaby' password = 'admin@123' phone = 5656 }"]

PyYAML 模块中的转换表

下表是 PyYAML 模块用于将 Python 对象转换为等效 YAML 的。**dump()** 方法在编码时使用转换。

YAML 标签Python 类型
!!null
!!boolBool
!!floatFloat
!!intint
!!binarystr (Python3 中的字节)
!!timestampDatetime.datetime
!!omap, !!pairs对列表
!!setSet
!!seqlist
!!strstr 或 unicode (Python 中的 str)
!!mapdict

YAML 错误

YAML 解析器在出现任何错误时会引发一个名为 **YAMLError** 的异常。借助此错误,我们可以调试问题。因此,建议在 try-except 块中使用 YAML 序列化代码。让我们理解以下示例。

示例 -

Token

令牌通常用于低级应用程序,例如语法高亮。我们可以使用 **scan()** 方法生成一组令牌。让我们理解以下示例。

示例 -

输出

StreamStartToken(encoding=None)
DocumentStartToken()
BlockMappingStartToken()
KeyToken()
ScalarToken(plain=True, style=None, value='UserName')
ValueToken()
ScalarToken(plain=True, style=None, value='Antonio')
KeyToken()
ScalarToken(plain=True, style=None, value='Password')
ValueToken()
ScalarToken(plain=True, style=None, value='fire123 *')
KeyToken()
ScalarToken(plain=True, style=None, value='phone')
ValueToken()
ScalarToken(plain=True, style=None, value='9879098')
KeyToken()
ScalarToken(plain=True, style=None, value='Skills')
ValueToken()
ScalarToken(plain=True, style=None, value='-Python -SQL -Django -Rest Framework -JavaScript')
BlockEndToken()
DocumentEndToken()
StreamEndToken()

Python YAML 到 XML

YAML 数据可以使用 **XMLPlain** 模块转换为 XML 格式。XML 是 **eXtensible Markup Language** 的缩写,它使用 HTML 标签来定义标签。

**obj_from_yaml()** 方法用于从 YAML 流或字符串生成 XML plain 对象。为了保持 XML plain 对象元素的顺序,YAML 流存储为 **OrderDict**。

让我们以包含员工详细信息的示例 YAML 文件为例,并将其转换为 XML 文件。

示例 -

让我们理解代码实现。

示例 -

结论

在本教程中,我们学习了 YAML 和 **PyYAML** 模块的一些重要概念。我们涵盖了如何创建自定义标签,将 YAML 文件的内容作为字典加载到我们的 Python 程序中。我们还讨论了如何操作 YAML 格式的文件。本教程包含了该库的相当简短和基本的功能。