一、简介
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函数,以确保不会执行潜在的恶意代码。
领取专属 10元无门槛券
私享最新 技术干货