首页
学习
活动
专区
工具
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元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券
http://www.vxiaotou.com