首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

每日一模块:pyyaml

一、简介

PyYAML是一个用于Python的YAML解析器和发射器。YAML是一种人类友好的数据序列化标准,常用于配置文件和数据交换。通过PyYAML,我们可以轻松地将Python对象序列化为YAML格式的字符串,也可以将YAML格式的字符串反序列化为Python对象。

二、安装

首先,你需要安装PyYAML。使用pip可以轻松完成安装:

pip install pyyaml

三、基本使用

1. 序列化(Python对象转为YAML)

import yaml

def serialize_to_yaml():

data = {

'name': '老王',

'age': 25,

'city': '北京'

}

yaml_string = yaml.dump(data)

print(yaml_string)

# 调用函数

serialize_to_yaml()

输出:

age: 25

city: 北京

name: 老王

2. 反序列化(YAML转为Python对象)

import yaml

def deserialize_from_yaml():

yaml_string = """

age: 25

city: 北京

name: 老王

"""

data = yaml.safe_load(yaml_string)

print(data)

# 调用函数

deserialize_from_yaml()

输出:

{'name': '老王', 'age': 25, 'city': '北京'}

四、高级功能

1. 自定义标签和构造函数

PyYAML允许你自定义YAML标签和构造函数,以便处理Python中不存在的类型。这通常涉及到编写自定义的构造函数,并在加载时指定这些函数。

# 首先,假设你有一个名为 Person 的 Python 类,它接受名字和年龄作为参数:

class Person:

def __init__(self, name, age):

self.name = name

self.age = age

def __repr__(self):

return f"Person(name={self.name}, age={self.age})"

然后,你可以使用 PyYAML 的 add_constructor 方法来添加一个构造函数,用于处理带有自定义标签的 YAML 数据。构造函数将在解析 YAML 时被调用,并将 YAML 节点的内容传递给 Person 类的构造函数。

import yaml

from yaml.constructor import Constructor

# 自定义构造函数

def person_constructor(loader, node):

value = loader.construct_mapping(node)

name = value['name']

age = value.get('age', None)  # age 可能是可选的

return Person(name, age)

# 创建一个自定义的构造函数

class MyConstructor(Constructor):

pass

# 继承并添加自定义构造函数

MyConstructor.add_constructor('!person', person_constructor)

# 使用自定义构造函数加载 YAML

yaml_string = """

- !person

name: Alice

age: 30

- !person

name: Bob

# age is optional

"""

# 加载 YAML 数据时使用自定义构造函数

data = yaml.load(yaml_string, Loader=yaml.Loader, custom_constructor=MyConstructor)

# 输出结果

print(data)  # 输出: [Person(name=Alice, age=30), Person(name=Bob, age=None)]

在这个例子中,定义了一个名为person_constructor 的函数,它接收一个加载器(loader)和一个节点(node),并从节点中提取出 name和age来创建Person类的实例。然后,我们创建了一个自定义的构造函数类MyConstructor,并为其添加了 !person标签的构造函数。最后,使用yaml.load 方法并传入自定义构造函数类来加载 YAML 数据。

2. 转储和加载多文档

你可以使用yaml.dump_all和yaml.safe_load_all函数来一次性转储或加载多个YAML文档。

import yaml

# 多个 Python 对象

data = [

{'name': 'Alice', 'age': 30},

{'name': 'Bob', 'age': 25},

{'name': 'Charlie', 'age': 35},

]

# 使用 dump_all 将多个对象转储为多个 YAML 文档到文件中

with open('users.yaml', 'w') as outfile:

yaml.dump_all(data, outfile, default_flow_style=False)

"""

age: 30

name: Alice

---

age: 25

name: Bob

---

age: 35

name: Charlie

"""

# 使用 safe_load_all 从文件中加载多个 YAML 文档为 Python 对象列表

with open('users.yaml', 'r') as infile:

loaded_data = list(yaml.safe_load_all(infile))

# 也可以使用load_all

# loaded_data = list(yaml.load_all(infile, Loader=yaml.FullLoader))

# 输出加载后的 Python 对象列表

for item in loaded_data:

print(item)

3. 定制转储和加载

PyYAML提供了多种参数来定制转储和加载行为,比如控制缩进、行宽、是否使用块样式或流样式等。

import yaml

data = {

'name': 'John Doe',

'age': 30,

'hobbies': ['reading', 'gaming', 'traveling'],

'address': {

'street': '123 Main St',

'city': 'Anytown',

'country': 'Country'

}

}

# 定制转储行为

dumped_yaml = yaml.dump(data, default_flow_style=False, sort_keys=True, indent=4, width=60)

print(dumped_yaml)

import yaml

yaml_string = """

name: John Doe

age: 30

hobbies:

- reading

- gaming

- traveling

address:

street: 123 Main St

city: Anytown

country: Country

"""

# 使用safe_load加载YAML字符串

loaded_data = yaml.safe_load(yaml_string)

print(loaded_data)

参数说明:

•default_flow_style=False:默认情况下,PyYAML会使用块样式(block style)来转储数据,除非数据是简单的键值对或列表。设置default_flow_style=True会使PyYAML尽可能使用流样式(flow style)。

•sort_keys=True:对字典的键进行排序。这在需要可预测的输出顺序时很有用。

•indent=4:设置缩进宽度为4个空格。默认是2个空格。

•width=60:设置每行的最大宽度。当内容超过这个宽度时,PyYAML会尝试将内容换行。

4. 安全加载

始终使用yaml.safe_load和yaml.safe_load_all来安全地加载YAML数据,以防止潜在的安全风险。

5. 错误处理

PyYAML提供了详细的错误信息,帮助你定位并解决YAML解析和序列化过程中的问题。

import yaml

# 解析yaml文件

try:

with open('data.yaml', 'r') as file:

data = yaml.safe_load(file)

except yaml.YAMLError as exc:

print(exc)

# python对象序列化

data = {

'name': 'Alice',

'age': 30,

'complex_object': set([1, 2, 3])  # 集合类型不能直接序列化为YAML

}

try:

yaml_string = yaml.dump(data)

except yaml.YAMLError as exc:

print(exc)

6. 日期和时间处理

PyYAML可以处理日期和时间对象,默认将其转换为Python的datetime类型。

7. 锚点和别名

PyYAML支持YAML的锚点和别名功能,允许你在YAML文件中引用其他部分的内容。

在YAML中,锚点(&)和别名(*)是两种用于引用其他部分内容的机制。锚点用于定义一个可以引用的标识符,而别名则用于引用这个标识符。这种机制可以使得YAML文件更加简洁和易于维护,尤其是当文件中存在大量重复数据时。

• data.yaml文件

defaults: &defaults

adapter:  postgres

host:     localhost

development:

database: dev

<<: *defaults

test:

database: test

<<: *defaults

在这个例子中,我们定义了一个名为defaults的锚点,它包含了一些默认的数据库配置。然后,在development和test配置中,我们使用<<: *defaults来合并这些默认配置。这实际上是一个YAML的合并键(merge key),它允许我们将多个映射合并到一个映射中。

import yaml

# 加载YAML文件

with open('data.yaml', 'r') as file:

data = yaml.safe_load(file)

# 打印加载的数据

print(data)

8. 保留顺序

PyYAML支持保留字典的插入顺序,这对于需要保持顺序的场景非常有用。

五、注意事项

在使用PyYAML处理来自不受信任的源的YAML数据时,务必使用yaml.safe_load和yaml.safe_load_all函数,以确保不会执行潜在的恶意代码。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OWk9c9Hry1K4b5oOh7p7Svuw0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券