228 lines
10 KiB
Markdown
228 lines
10 KiB
Markdown
# Python YAML:如何加载、读取和编写 YAML
|
||
|
||
> 原文:[https://python.land/data-processing/python-yaml](https://python.land/data-processing/python-yaml)
|
||
|
||
YAML 是“YAML 不是标记语言”的递归首字母缩写,是一种人类可读的数据序列化语言。它通常用于配置文件,但也可用于数据交换。最常用的 python YAML 解析器是 PyYAML,这是一个允许你加载、解析和编写 YAML 的库,很像 [Python 的 JSON](https://python.land/data-processing/working-with-json) 库帮助你使用 JSON。
|
||
|
||
这篇文章教你如何用 PyYAML 加载、读取和写入 YAML 文件。此外,您还将了解如何在您的系统上安装它,以及 YAML 与 JSON 等替代产品的比较。
|
||
|
||
目录
|
||
|
||
|
||
|
||
* 什么是 YAML?
|
||
* [为什么将 YAML 与 Python 结合使用?](#Why_use_YAML_with_Python "Why use YAML with Python?")
|
||
* [安装和导入 PyYAML](#Installing_and_importing_PyYAML "Installing and importing PyYAML")
|
||
* [用 Python 读取并解析 YAML 文件](#Reading_and_parsing_a_YAML_file_with_Python "Reading and parsing a YAML file with Python")
|
||
* [用 Python 解析 YAML 字符串](#Parsing_YAML_strings_with_Python "Parsing YAML strings with Python")
|
||
* [解析包含多个 YAML 文档的文件](#Parsing_files_with_multiple_YAML_documents "Parsing files with multiple YAML documents")
|
||
* [将 YAML 写入(或转储)到文件中](#Writing_or_dumping_YAML_to_a_file "Writing (or dumping) YAML to a file")
|
||
* [使用 Python 将 YAML 转换成 JSON】](#Convert_YAML_to_JSON_using_Python "Convert YAML to JSON using Python")
|
||
* [将 JSON 转换成 YAML](#Convert_JSON_to_YAML "Convert JSON to YAML")
|
||
* [PyYAML safe _ load()vs load()](#PyYAML_safe_load_vs_load "PyYAML safe_load() vs load()")
|
||
* [追加资源](#Addition_resources "Addition resources")
|
||
|
||
|
||
|
||
## 什么是 YAML?
|
||
|
||

|
||
|
||
YAML 标志
|
||
|
||
据[官网](https://yaml.org/)<sup>(1)</sup>**YAML 是一种对所有编程语言都友好的数据序列化语言。** YAML 最常用于配置文件,但也用于数据交换。
|
||
|
||
YAML 对于人类来说很容易写和读,即使对于非程序员来说也是如此。同时,解析 YAML 也很容易,尤其是使用 Python 和 PyYAML 库!它的人性化和可读性是 YAML 相对于其他格式的最大优势,比如 JSON 和 XML。
|
||
|
||
这些是 YAML 最突出的特征:
|
||
|
||
* 您可以在 YAML 文件中使用注释
|
||
* 您可以使用`---`分隔符在一个 YAML 文件中存储多个文档。Kubernetes 定义中经常使用的一个特性。
|
||
* 对人类来说很容易阅读
|
||
* 很容易为计算机解析
|
||
|
||
<sup>1)有趣的事实是,YAML 官方网站是以有效的 YAML 文件的形式编写的。</sup>
|
||
|
||
## 为什么将 YAML 与 Python 结合使用?
|
||
|
||
如果你问我,YAML 是完美的配置文件。这正是我和许多其他开发人员使用它最多的方式。其他人似乎同意,因为许多大型项目,如 Docker 和 Kubernetes,使用 YAML 来定义部署。它的语法比常用的替代方法更丰富。ini 文件,但是看起来还是不错的,并且易于编写和解析。
|
||
|
||
不过,将 YAML 与 Python 结合使用也有一些缺点:
|
||
|
||
* YAML 不是标准 Python 库的一部分,而 XML 和 JSON 是
|
||
* 它对缩进的依赖有时令人沮丧(不过,Python 开发人员已经习惯了,对吧?)
|
||
* 对于简单的用例,比如简单对象的数据交换,它可能有点太通用了。
|
||
|
||
如果您正在寻找一种良好的数据交换和存储格式,我推荐 JSON、XML 或其他更有效的格式,如协议缓冲区和 Avro。
|
||
|
||
## 安装和导入 PyYAML
|
||
|
||
有多个 Python 包可以解析 YAML 数据。然而,PyYAML 是解析 YAML 最流行也是最完整的实现。PyYAML 不是标准 Python 库的一部分,这意味着您需要用 Pip 来[安装它。使用以下命令安装 PyYAML,最好是在](https://python.land/virtual-environments/installing-packages-with-pip)[虚拟环境](https://python.land/virtual-environments)中:
|
||
|
||
```py
|
||
$ pip install pyyaml
|
||
```
|
||
|
||
在某些系统上,您需要使用 pip3:
|
||
|
||
```py
|
||
$ pip3 install pyyaml
|
||
```
|
||
|
||
要在您的脚本中使用 PyYAML,[导入模块](https://python.land/project-structure/python-modules),如下所示。请注意,您没有导入“pyyaml”,而只是导入了“yaml”:
|
||
|
||
```py
|
||
import yaml
|
||
```
|
||
|
||
## 用 Python 读取并解析 YAML 文件
|
||
|
||
一旦导入了 YAML 解析器,我们就可以加载一个 YAML 文件并解析它。YAML 文件通常带有扩展名`.yaml`或`.yml`。让我们以下面的 YAML 文件为例,名为`config.yaml`:
|
||
|
||
```py
|
||
rest:
|
||
url: "https://example.org/primenumbers/v1"
|
||
port: 8443
|
||
|
||
prime_numbers: [2, 3, 5, 7, 11, 13, 17, 19]
|
||
```
|
||
|
||
加载、解析和使用这个配置文件非常类似于用 [Python JSON 库](https://python.land/data-processing/working-with-json)加载 JSON。首先,我们[打开文件](https://python.land/operating-system/python-files)。接下来,我们用`yaml.safe_load()`函数解析它。请注意,我对输出做了一点修改,以便于您阅读:
|
||
|
||
```py
|
||
>>> import yaml
|
||
>>> with open('config.yml', 'r') as file
|
||
... prime_service = yaml.safe_load(file)
|
||
|
||
>>> prime_service
|
||
{'rest':
|
||
{ 'url': 'https://example.org/primenumbers/v1',
|
||
'port': 8443
|
||
},
|
||
'prime_numbers': [2, 3, 5, 7, 11, 13, 17, 19]}
|
||
|
||
>>> prime_service['rest']['url']
|
||
https://example.org/primenumbers/v1
|
||
```
|
||
|
||
YAML 解析器返回最符合数据的常规 Python 对象。在这种情况下,它是一个 [Python 字典](https://python.land/python-data-types/dictionaries)。这意味着可以使用所有常规的字典特性,比如使用带有默认值的`get()`。
|
||
|
||
这是同一个例子,但是是交互式的,所以你可以自己尝试一下:
|
||
|
||
[https://crumb . sh/embed/xbk 87 vueyxv](https://crumb.sh/embed/XBK87vueyxv)
|
||
|
||
## 用 Python 解析 YAML 字符串
|
||
|
||
您可以使用`yaml.safe_load()`来解析各种有效的 YAML 字符串。这里有一个例子,它将一个简单的条目列表解析成一个 [Python 列表](https://python.land/python-data-types/python-list):
|
||
|
||
```py
|
||
>>> import yaml
|
||
>>>
|
||
>>> names_yaml = """
|
||
... - 'eric'
|
||
... - 'justin'
|
||
... - 'mary-kate'
|
||
... """
|
||
>>>
|
||
>>> names = yaml.safe_load(names_yaml)
|
||
>>> names
|
||
['eric', 'justin', 'mary-kate']
|
||
```
|
||
|
||
## 解析包含多个 YAML 文档的文件
|
||
|
||
YAML 允许你在一个文件中定义多个文档,用三个破折号(`---`)分隔它们。PyYAML 也会很乐意解析这样的文件,并返回一个文档列表。您可以通过使用`yaml.safe_load_all()` [功能](https://python.land/introduction-to-python/functions)来实现。该函数返回一个生成器,该生成器将依次返回所有文档。
|
||
|
||
注意,只要从 YAML 读取文档,就需要打开文件,所以必须在`with`子句内进行处理。下面是一个演示此功能的交互式示例:
|
||
|
||
[https://crumb.sh/embed/3FkJXZuuK4H](https://crumb.sh/embed/3FkJXZuuK4H)
|
||
|
||
## 将 YAML 写入(或转储)到文件中
|
||
|
||
虽然大多数人只会把 YAML 作为配置文件来读,但是写 YAML 也很方便。示例用例可能是:
|
||
|
||
* 使用用户的当前设置创建初始配置文件
|
||
* 将程序状态保存在一个易于阅读的文件中(而不是使用 Pickle 之类的东西)
|
||
|
||
在以下示例中,我们将:
|
||
|
||
* 像我们之前做的那样创建一个带有姓名的列表
|
||
* 用`yaml.dump`将名称保存到 YAML 格式的文件中
|
||
* 阅读并打印文件,作为一切按预期工作的证明
|
||
|
||
给你:
|
||
|
||
[https://crumb . sh/embed/maabpr 3 qx](https://crumb.sh/embed/mAvaBpr3qPx)
|
||
|
||
下面是与非交互式示例相同的代码:
|
||
|
||
```py
|
||
import yaml
|
||
|
||
names_yaml = """
|
||
- 'eric'
|
||
- 'justin'
|
||
- 'mary-kate'
|
||
"""
|
||
|
||
names = yaml.safe_load(names_yaml)
|
||
|
||
with open('names.yaml', 'w') as file:
|
||
yaml.dump(names, file)
|
||
|
||
print(open('names.yaml').read())
|
||
```
|
||
|
||
```py
|
||
- eric
|
||
- justin
|
||
- mary-kate
|
||
```
|
||
|
||
## 使用 Python 将 YAML 转换成 JSON】
|
||
|
||
如果您需要将 YAML 转换成 JSON,您可以像上面那样简单地解析 YAML。在下一步中,您可以使用 [JSON 模块](https://python.land/data-processing/working-with-json)将对象转换成 JSON。
|
||
|
||
在本例中,我们打开一个基于 YAML 的配置文件,用 PyYAML 解析它,然后用 JSON 模块将其写入一个 JSON 文件:
|
||
|
||
[https://crumb.sh/embed/rAUgstafYtA](https://crumb.sh/embed/rAUgstafYtA)
|
||
|
||
下面是与非交互式示例相同的代码:
|
||
|
||
```py
|
||
import yaml
|
||
import json
|
||
|
||
with open('config.yml', 'r') as file:
|
||
configuration = yaml.safe_load(file)
|
||
|
||
with open('config.json', 'w') as json_file:
|
||
json.dump(configuration, json_file)
|
||
```
|
||
|
||
## 将 JSON 转换成 YAML
|
||
|
||
为了完整起见,让我们反过来做:将 JSON 转换成 YAML:
|
||
|
||
[https://crumb.sh/embed/CjAnBJVynyU](https://crumb.sh/embed/CjAnBJVynyU)
|
||
|
||
如何用 Python 将 JSON 转换成 YAML
|
||
|
||
## PyYAML safe _ load()vs load()
|
||
|
||
你会遇到很多 PyYAML 用法的例子,其中使用了`load()`而不是`safe_load()`。我故意到现在才告诉你`load()`功能。由于大多数人都有工作要做,并且倾向于快速复制粘贴一些示例代码,我希望他们使用最安全的方法用 Python 解析 YAML。
|
||
|
||
然而,如果你对这两者之间的区别感到好奇,这里有一个简短的总结:`load()`是一个非常强大的函数,就像[泡菜](https://docs.python.org/3/library/pickle.html),如果你知道那个函数的话。这两种方法都非常不安全,因为它们允许攻击者执行任意代码。PyYAML 的 load 函数允许您序列化和反序列化完整的 Python 对象,甚至执行 Python 代码,包括调用`os.system`库,该库可以在您的系统上执行任何命令。
|
||
|
||
在最近的 PyYAML 版本中,`load()`函数被弃用,当您以不安全的方式使用它时,它会发出一个很大的警告。
|
||
|
||
如果你像我们 99%的人一样解析常规的 YAML 文件,你应该总是使用`safe_load()`,因为它只包含了 load 函数的一个子集。所有可怕的、任意代码执行类型的东西都被剔除了。
|
||
|
||
## 追加资源
|
||
|
||
以下是您可能想继续使用的一些资源:
|
||
|
||
* 【PyYAML 官方文档
|
||
* [如何用 Python 打开、读取和写入文件](https://python.land/operating-system/python-files)
|
||
* [在 Python 中使用 JSON](https://python.land/data-processing/working-with-json)
|
||
* [命令行上的 JSON](https://python.land/the-unix-shell/process-json-with-jq) |