一、PyYAML 库概述
在Python开发过程中,配置文件的管理是项目开发中不可或缺的一环,相比于传统的INI、JSON配置文件,YAML凭借简洁易读、支持注释、可嵌套、支持列表与字典混合使用的语法优势,成为现代项目配置文件的首选格式,而PyYAML就是Python生态中专门用于解析和生成YAML文件的标准库。

PyYAML的核心工作原理是实现Python数据类型与YAML格式数据的双向转换,它可以将Python中的字典、列表、字符串、数字、布尔值、None等基础数据类型序列化为YAML格式文本,也能将YAML格式的文本或文件反序列化为Python可直接操作的数据对象,底层基于YAML 1.1规范实现解析,兼容主流YAML语法规则。
该库采用MIT License开源,允许商业与非商业项目自由使用、修改和分发。其优点是语法简洁、使用简单、兼容性强、支持复杂数据结构,缺点是解析大型YAML文件时性能略低于部分专用解析库,且存在一定的安全风险,不建议解析不可信的YAML内容。
二、PyYAML 安装方法
PyYAML作为Python第三方库,无法通过Python内置模块直接调用,需要使用pip包管理器进行安装,安装命令支持普通安装与指定版本安装,适配Windows、macOS、Linux全平台系统。
2.1 基础安装命令
打开系统命令提示符(CMD)、PowerShell或终端,直接执行以下pip命令即可完成安装:
pip install pyyaml2.2 指定版本安装
如果项目需要固定PyYAML版本以保证兼容性,可以使用以下命令指定版本安装,这里以6.0版本为例:
pip install pyyaml==6.02.3 升级PyYAML
若本地已安装旧版本PyYAML,想要升级到最新稳定版本,执行升级命令:
pip install --upgrade pyyaml安装完成后,可在Python交互环境中执行import yaml,若没有报错则说明安装成功,可正常使用。
三、PyYAML 基础使用方法
PyYAML的核心操作分为两大类:YAML文件/字符串解析(加载) 和 Python对象转YAML(转储),分别对应yaml.load()、yaml.safe_load()、yaml.dump()等核心方法,其中safe_load()是官方推荐的安全解析方法,可避免执行恶意代码。
3.1 YAML字符串解析为Python对象
当我们需要将YAML格式的字符串转换为Python字典、列表等对象时,使用yaml.safe_load()方法,该方法只解析基础数据类型,不执行自定义Python对象,安全性更高。
# 导入PyYAML库
import yaml
# 定义YAML格式的字符串
yaml_str = """
name: 测试项目
version: 1.0.0
author: 开发者
features:
- 配置解析
- 数据序列化
- 跨平台兼容
is_online: true
port: 8080
"""
# 将YAML字符串解析为Python字典
data = yaml.safe_load(yaml_str)
# 打印解析后的数据类型与内容
print("解析后的数据类型:", type(data))
print("解析后的数据内容:", data)
# 单独获取指定字段
print("项目名称:", data["name"])
print("项目端口:", data["port"])代码说明:
- 首先导入yaml库,这是使用PyYAML的前提;
- 定义多行YAML字符串,包含字符串、数字、列表、布尔值四种数据类型;
- 调用
yaml.safe_load()方法完成解析,返回Python字典对象; - 可通过字典键名直接获取对应的值,实现YAML数据的读取与使用。
3.2 Python对象转换为YAML字符串
将Python中的字典、列表等对象转换为标准YAML格式字符串,使用yaml.dump()方法,该方法会自动按照YAML语法格式化数据,生成可读性极高的文本内容。
import yaml
# 定义Python字典对象
python_data = {
"app_name": "PyYAML教程",
"language": "Python",
"tags": ["YAML", "配置文件", "数据解析"],
"status": "开发中",
"config": {
"debug": True,
"log_path": "./logs/app.log"
}
}
# 将Python对象转为YAML字符串
yaml_result = yaml.dump(python_data, allow_unicode=True, sort_keys=False)
# 打印生成的YAML内容
print("生成的YAML格式内容:")
print(yaml_result)代码说明:
allow_unicode=True参数允许显示中文字符,避免中文乱码;sort_keys=False参数禁止自动排序字典键,保持原有数据顺序;- 转换后的YAML内容自动缩进、分行,符合YAML标准语法,可读性强。
3.3 读取本地YAML文件
在实际项目中,YAML内容通常存储在.yaml或.yml后缀的文件中,PyYAML可直接读取本地文件并解析,无需手动处理文件读取逻辑。
首先创建一个config.yaml文件,写入以下内容:
# 项目基础配置
database:
host: 127.0.0.1
port: 3306
username: root
password: 123456
db_name: test_db
server:
ip: 0.0.0.0
port: 8000
max_connect: 100然后编写Python代码读取并解析该文件:
import yaml
# 打开YAML文件并读取内容
with open("config.yaml", "r", encoding="utf-8") as f:
# 安全解析YAML文件内容
config_data = yaml.safe_load(f)
# 输出解析后的数据库配置
print("数据库地址:", config_data["database"]["host"])
print("数据库端口:", config_data["database"]["port"])
print("服务端口:", config_data["server"]["port"])代码说明:
- 使用
with open()语句打开文件,自动处理文件关闭操作,避免资源泄漏; - 指定编码为
utf-8,确保中文配置内容正常读取; - 直接将文件对象传入
yaml.safe_load(),即可完成文件解析,返回Python字典。
3.4 将Python对象写入YAML文件
除了读取YAML文件,PyYAML还支持将Python数据直接写入本地YAML文件,实现配置文件的生成与修改。
import yaml
# 定义需要写入的配置数据
write_data = {
"system": {
"os": "Windows/Linux/macOS",
"python_version": "3.8+",
"memory": "4GB+"
},
"modules": {
"pyyaml": "6.0",
"requests": "2.31.0",
"pandas": "2.1.0"
}
}
# 将数据写入YAML文件
with open("system_config.yaml", "w", encoding="utf-8") as f:
# 写入文件,保留中文,不排序键
yaml.dump(write_data, f, allow_unicode=True, sort_keys=False, indent=2)
print("YAML文件写入完成!")代码说明:
indent=2参数设置YAML文件缩进为2个空格,让文件格式更美观;- 写入完成后,会在当前目录生成
system_config.yaml文件,内容符合标准YAML格式; - 该方法常用于项目初始化时自动生成配置文件。
3.5 解析YAML列表与嵌套结构
YAML支持多层嵌套结构与复杂列表,PyYAML可完美解析这类复杂数据,适配企业级项目的复杂配置场景。
import yaml
# 包含嵌套字典与多层列表的YAML字符串
complex_yaml = """
project:
name: 电商平台
modules:
- name: 用户模块
functions: [登录, 注册, 修改密码]
- name: 商品模块
functions: [商品展示, 商品搜索, 购物车]
version: 2.1.0
"""
# 解析复杂YAML数据
complex_data = yaml.safe_load(complex_yaml)
# 读取嵌套数据
print("项目名称:", complex_data["project"]["name"])
print("第一个模块名称:", complex_data["project"]["modules"][0]["name"])
print("用户模块功能:", complex_data["project"]["modules"][0]["functions"])代码说明:
- YAML支持列表嵌套字典、字典嵌套列表的复杂结构;
- PyYAML解析后,可通过多层键名与列表索引精准获取目标数据;
- 完全满足微服务、分布式项目的复杂配置读取需求。
四、PyYAML 高级使用技巧
4.1 安全解析与不安全解析的区别
PyYAML提供yaml.load()和yaml.safe_load()两种解析方法,yaml.load()已被官方标记为不安全,因为它可以解析并执行自定义Python对象,若解析来自网络或不可信来源的YAML文件,可能导致代码执行漏洞。
import yaml
# 不安全的解析方式(不推荐)
# 仅用于本地可信YAML内容,禁止解析外部数据
unsafe_yaml = """
test: !!python/object/apply:subprocess.Popen
- [calc.exe]
"""
# 执行后会打开系统计算器,存在安全风险
# yaml.load(unsafe_yaml, Loader=yaml.UnsafeLoader)
# 安全解析方式(官方推荐)
# 无法执行Python对象,仅解析基础数据类型
safe_data = yaml.safe_load(unsafe_yaml)
print("安全解析结果:", safe_data)代码说明:
- 生产环境中必须使用
yaml.safe_load(),杜绝安全漏洞; yaml.load()需要指定Loader,且仅适用于完全可信的本地数据;- 安全解析会忽略自定义Python对象,保证程序运行安全。
4.2 批量解析多个YAML文档
YAML支持在一个文件中编写多个文档,使用`分隔,PyYAML可通过yaml.safe_load_all()`方法批量解析所有文档,返回可迭代对象。
创建multi_docs.yaml文件:
doc: 1
title: 第一个文档
content: 测试内容1
doc: 2
title: 第二个文档
content: 测试内容2
doc: 3
title: 第三个文档
content: 测试内容3解析代码:
import yaml
# 读取包含多个文档的YAML文件
with open("multi_docs.yaml", "r", encoding="utf-8") as f:
# 批量解析所有文档
docs = yaml.safe_load_all(f)
# 遍历所有文档内容
for idx, doc in enumerate(docs, 1):
print(f"第{idx}个文档:", doc)代码说明:
yaml.safe_load_all()返回生成器对象,节省内存;- 适用于存储多组配置、多组测试数据的场景;
- 遍历即可获取每个独立文档的Python对象。
4.3 自定义YAML输出格式
通过yaml.dump()的参数可自定义YAML输出格式,包括缩进、换行、浮点数精度、是否显示默认值等,满足不同项目的格式要求。
import yaml
custom_data = {
"name": "自定义格式",
"values": [1.23456, 2.34567, 3.45678],
"info": {
"author": "测试",
"time": "2026-01-01"
}
}
# 自定义输出格式
custom_yaml = yaml.dump(
custom_data,
allow_unicode=True,
sort_keys=False,
indent=4,
default_flow_style=False,
width=50
)
print(custom_yaml)代码说明:
default_flow_style=False强制使用块样式输出,避免压缩格式;width=50限制每行最大宽度,提升可读性;- 自定义格式后的YAML文件更符合团队开发规范。
五、PyYAML 实际项目应用案例
在实际Python项目中,PyYAML最常用于项目配置文件管理、接口自动化测试数据存储、爬虫配置管理、机器学习参数配置等场景,下面以Web项目配置管理为例,展示完整的实战代码。
5.1 实战场景:Web项目配置管理工具
开发一个通用的配置管理工具,实现YAML配置文件的读取、修改、保存功能,支持多环境配置切换(开发环境、测试环境、生产环境)。
import yaml
import os
class YamlConfigManager:
"""YAML配置文件管理类"""
def __init__(self, config_path="web_config.yaml"):
self.config_path = config_path
self.config_data = None
# 初始化时加载配置文件
self.load_config()
def load_config(self):
"""加载YAML配置文件"""
if not os.path.exists(self.config_path):
raise FileNotFoundError(f"配置文件{self.config_path}不存在!")
with open(self.config_path, "r", encoding="utf-8") as f:
self.config_data = yaml.safe_load(f)
print("配置文件加载成功!")
def get_config(self, env="dev"):
"""获取指定环境的配置"""
if env not in self.config_data:
raise ValueError(f"不支持{env}环境配置!")
return self.config_data[env]
def update_config(self, env, key, value):
"""修改指定环境的配置"""
if env not in self.config_data:
self.config_data[env] = {}
self.config_data[env][key] = value
# 保存修改后的配置
self.save_config()
print(f"{env}环境{key}配置修改为{value}成功!")
def save_config(self):
"""保存配置到YAML文件"""
with open(self.config_path, "w", encoding="utf-8") as f:
yaml.dump(self.config_data, f, allow_unicode=True, sort_keys=False, indent=2)
# 初始化配置文件内容(首次运行使用)
if not os.path.exists("web_config.yaml"):
init_data = {
"dev": {
"host": "127.0.0.1",
"port": 8000,
"debug": True,
"database": "sqlite:///dev.db"
},
"test": {
"host": "192.168.1.100",
"port": 8080,
"debug": False,
"database": "mysql://test:test@localhost/test_db"
},
"prod": {
"host": "10.0.0.1",
"port": 80,
"debug": False,
"database": "mysql://prod:prod@localhost/prod_db"
}
}
with open("web_config.yaml", "w", encoding="utf-8") as f:
yaml.dump(init_data, f, allow_unicode=True, sort_keys=False, indent=2)
# 实战调用
if __name__ == "__main__":
# 创建配置管理器对象
config_manager = YamlConfigManager()
# 获取开发环境配置
dev_config = config_manager.get_config("dev")
print("开发环境配置:", dev_config)
# 修改测试环境端口
config_manager.update_config("test", "port", 8888)
# 获取修改后的测试环境配置
test_config = config_manager.get_config("test")
print("修改后测试环境配置:", test_config)代码说明:
- 封装
YamlConfigManager类,实现配置加载、读取、修改、保存的完整功能; - 支持多环境配置切换,适配Web项目的不同运行环境;
- 自动初始化配置文件,无需手动创建,降低使用成本;
- 代码可直接集成到Django、Flask、FastAPI等Web框架中。
相关资源
- Pypi地址:https://pypi.org/project/PyYAML/
- Github地址:https://github.com/yaml/pyyaml
- 官方文档地址:https://pyyaml.org/wiki/PyYAMLDocumentation
关注我,每天分享一个实用的Python自动化工具。

