geekdoc-python-zh/docs/pythonland/57.md

228 lines
10 KiB
Markdown
Raw Permalink Normal View History

2024-03-03 22:54:39 +08:00
# 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](img/4268852dc75473c2298eecbbf5cec6c5.png)
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)