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

228 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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)