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

10 KiB
Raw Permalink Blame History

Python YAML:如何加载、读取和编写 YAML

原文:https://python.land/data-processing/python-yaml

YAML 是“YAML 不是标记语言”的递归首字母缩写,是一种人类可读的数据序列化语言。它通常用于配置文件,但也可用于数据交换。最常用的 python YAML 解析器是 PyYAML这是一个允许你加载、解析和编写 YAML 的库,很像 Python 的 JSON 库帮助你使用 JSON。

这篇文章教你如何用 PyYAML 加载、读取和写入 YAML 文件。此外,您还将了解如何在您的系统上安装它,以及 YAML 与 JSON 等替代产品的比较。

目录

什么是 YAML

YAML

YAML 标志

官网(1)YAML 是一种对所有编程语言都友好的数据序列化语言。 YAML 最常用于配置文件,但也用于数据交换。

YAML 对于人类来说很容易写和读,即使对于非程序员来说也是如此。同时,解析 YAML 也很容易,尤其是使用 Python 和 PyYAML 库!它的人性化和可读性是 YAML 相对于其他格式的最大优势,比如 JSON 和 XML。

这些是 YAML 最突出的特征:

  • 您可以在 YAML 文件中使用注释
  • 您可以使用---分隔符在一个 YAML 文件中存储多个文档。Kubernetes 定义中经常使用的一个特性。
  • 对人类来说很容易阅读
  • 很容易为计算机解析

1)有趣的事实是YAML 官方网站是以有效的 YAML 文件的形式编写的。

为什么将 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最好是在虚拟环境中:

$ pip install pyyaml

在某些系统上,您需要使用 pip3:

$ pip3 install pyyaml

要在您的脚本中使用 PyYAML导入模块如下所示。请注意您没有导入“pyyaml”而只是导入了“yaml”:

import yaml

用 Python 读取并解析 YAML 文件

一旦导入了 YAML 解析器,我们就可以加载一个 YAML 文件并解析它。YAML 文件通常带有扩展名.yaml.yml。让我们以下面的 YAML 文件为例,名为config.yaml:

rest:
  url: "https://example.org/primenumbers/v1"
  port: 8443

prime_numbers: [2, 3, 5, 7, 11, 13, 17, 19]

加载、解析和使用这个配置文件非常类似于用 Python JSON 库加载 JSON。首先我们打开文件。接下来,我们用yaml.safe_load()函数解析它。请注意,我对输出做了一点修改,以便于您阅读:

>>> 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 字典。这意味着可以使用所有常规的字典特性,比如使用带有默认值的get()

这是同一个例子,但是是交互式的,所以你可以自己尝试一下:

https://crumb . sh/embed/xbk 87 vueyxv

用 Python 解析 YAML 字符串

您可以使用yaml.safe_load()来解析各种有效的 YAML 字符串。这里有一个例子,它将一个简单的条目列表解析成一个 Python 列表:

>>> 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() 功能来实现。该函数返回一个生成器,该生成器将依次返回所有文档。

注意,只要从 YAML 读取文档,就需要打开文件,所以必须在with子句内进行处理。下面是一个演示此功能的交互式示例:

https://crumb.sh/embed/3FkJXZuuK4H

将 YAML 写入(或转储)到文件中

虽然大多数人只会把 YAML 作为配置文件来读,但是写 YAML 也很方便。示例用例可能是:

  • 使用用户的当前设置创建初始配置文件
  • 将程序状态保存在一个易于阅读的文件中(而不是使用 Pickle 之类的东西)

在以下示例中,我们将:

  • 像我们之前做的那样创建一个带有姓名的列表
  • yaml.dump将名称保存到 YAML 格式的文件中
  • 阅读并打印文件,作为一切按预期工作的证明

给你:

https://crumb . sh/embed/maabpr 3 qx

下面是与非交互式示例相同的代码:

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())
- eric
- justin
- mary-kate

使用 Python 将 YAML 转换成 JSON】

如果您需要将 YAML 转换成 JSON您可以像上面那样简单地解析 YAML。在下一步中您可以使用 JSON 模块将对象转换成 JSON。

在本例中,我们打开一个基于 YAML 的配置文件,用 PyYAML 解析它,然后用 JSON 模块将其写入一个 JSON 文件:

https://crumb.sh/embed/rAUgstafYtA

下面是与非交互式示例相同的代码:

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

如何用 Python 将 JSON 转换成 YAML

PyYAML safe _ load()vs load()

你会遇到很多 PyYAML 用法的例子,其中使用了load()而不是safe_load()。我故意到现在才告诉你load()功能。由于大多数人都有工作要做,并且倾向于快速复制粘贴一些示例代码,我希望他们使用最安全的方法用 Python 解析 YAML。

然而,如果你对这两者之间的区别感到好奇,这里有一个简短的总结:load()是一个非常强大的函数,就像泡菜如果你知道那个函数的话。这两种方法都非常不安全因为它们允许攻击者执行任意代码。PyYAML 的 load 函数允许您序列化和反序列化完整的 Python 对象,甚至执行 Python 代码,包括调用os.system库,该库可以在您的系统上执行任何命令。

在最近的 PyYAML 版本中,load()函数被弃用,当您以不安全的方式使用它时,它会发出一个很大的警告。

如果你像我们 99%的人一样解析常规的 YAML 文件,你应该总是使用safe_load(),因为它只包含了 load 函数的一个子集。所有可怕的、任意代码执行类型的东西都被剔除了。

追加资源

以下是您可能想继续使用的一些资源: