一、简介
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元无门槛券
私享最新 技术干货