Python中的PyYAML:YAML解析库详解
YAML 是一种人类可读的数据序列化语言,常用于配置文件(如 Docker Compose、Kubernetes 配置、Ansible Playbooks 等)。使用缩进表示层级结构(类似 Python)支持标量(字符串、数字、布尔)、列表和字典支持注释支持锚点(&)和引用(*)实现数据复用示例 YAML 文件(database:port: 5432features:- logging- cach
一、什么是 YAML?
YAML 是一种人类可读的数据序列化语言,常用于配置文件(如 Docker Compose、Kubernetes 配置、Ansible Playbooks 等)。其主要特点包括:
- 使用缩进表示层级结构(类似 Python)
- 支持标量(字符串、数字、布尔)、列表和字典
- 支持注释
- 支持锚点(&)和引用(*)实现数据复用
示例 YAML 文件(config.yaml):
database:
host: localhost
port: 5432
username: admin
password: secret
features:
- user_auth
- logging
- caching
debug: true
二、PyYAML 简介
PyYAML 是一个用于在 Python 中解析和生成 YAML 数据的第三方库。它支持完整的 YAML 1.1 规范,并提供了简单易用的 API。
主要功能:
- 将 YAML 字符串或文件加载为 Python 对象(如字典、列表)
- 将 Python 对象转储为 YAML 格式
- 支持自定义数据类型和标签
- 提供安全加载模式(防止任意代码执行)
三、安装 PyYAML
使用 pip 安装 PyYAML:
pip install pyyaml
注意:包名是
pyyaml,但导入时使用import yaml。
四、基本用法
1. 加载 YAML 数据(解析)
使用 yaml.load() 或推荐的安全方式 yaml.safe_load()。
import yaml
# 示例 YAML 字符串
yaml_str = """
name: Alice
age: 30
skills:
- Python
- Data Analysis
- Machine Learning
active: true
"""
# 解析 YAML 字符串
data = yaml.safe_load(yaml_str)
print(data)
# 输出:
# {'name': 'Alice', 'age': 30, 'skills': ['Python', 'Data Analysis', 'Machine Learning'], 'active': True}
从文件加载:
with open('config.yaml', 'r', encoding='utf-8') as file:
config = yaml.safe_load(file)
print(config)
2. 生成 YAML 数据(转储)
使用 yaml.dump() 将 Python 对象转换为 YAML 字符串。
data = {
'server': {
'host': '192.168.1.1',
'port': 8080,
'ssl': True
},
'users': ['alice', 'bob', 'charlie']
}
yaml_str = yaml.dump(data, default_flow_style=False, sort_keys=False)
print(yaml_str)
输出:
server:
host: 192.168.1.1
port: 8080
ssl: true
users:
- alice
- bob
- charlie
常用参数说明:
default_flow_style=False:使用缩进块风格而非内联风格sort_keys=False:保持字典键的原始顺序(PyYAML 默认排序,关闭以保留顺序)
五、高级特性
1. 锚点与引用(Anchors & Aliases)
YAML 支持通过 & 定义锚点,* 引用已定义的内容,避免重复。
defaults: &defaults
timeout: 30
retries: 3
service1:
<<: *defaults
url: https://api.service1.com
service2:
<<: *defaults
url: https://api.service2.com
timeout: 60
PyYAML 能正确解析此类结构,合并字段(<< 表示合并)。
2. 自定义 Python 对象序列化
可以注册自定义类型,实现复杂对象的 YAML 序列化。
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})"
# 注册序列化器
def person_representer(dumper, data):
return dumper.represent_mapping('!person', {'name': data.name, 'age': data.age})
yaml.add_representer(Person, person_representer)
# 使用
p = Person("Bob", 25)
print(yaml.dump(p))
# 输出:
# !person {age: 25, name: Bob}
反序列化需使用 yaml.add_constructor() 注册构造器。
六、安全注意事项
⚠️ 重要警告:不要使用 yaml.load() 处理不可信的 YAML 输入!
yaml.load() 支持任意 Python 对象构造,可能执行恶意代码:
malicious_yaml = """
!!python/object/apply:os.system ['echo "PWNED"']
"""
# yaml.load(malicious_yaml) # 危险!会执行系统命令
✅ 正确做法:始终使用 yaml.safe_load(),它仅支持标准 YAML 类型(str、int、list、dict 等),不执行任意代码。
如果需要加载自定义类型,应使用 yaml.full_load() 并确保输入可信。
七、常见问题与技巧
1. 保持字典顺序
Python 3.7+ 字典默认有序,但 PyYAML 默认会排序。可通过以下方式保留顺序:
from collections import OrderedDict
data = yaml.safe_load(yaml_str, Loader=yaml.SafeLoader)
# 或者指定加载器使用 OrderedDict
2. 处理中文字符
写入文件时注意编码:
with open('output.yaml', 'w', encoding='utf-8') as f:
yaml.dump(data, f, allow_unicode=True, default_flow_style=False)
设置 allow_unicode=True 避免中文被转义。
八、替代方案对比
| 库名 | 特点 |
|---|---|
| PyYAML | 功能全面,社区广泛,支持完整 YAML 规范 |
ruamel.yaml |
更现代,严格遵循 YAML 1.2 标准,更好保留格式和注释,适合配置文件编辑 |
strictyaml |
强调安全性与模式验证,适合处理用户输入 |
对于大多数项目,PyYAML 已足够;若需更高安全性或格式保留,可考虑 ruamel.yaml。
九、总结
PyYAML 是 Python 中处理 YAML 数据的事实标准库,具备以下优点:
- API 简洁直观
- 功能强大,支持复杂结构
- 社区成熟,文档丰富
但在使用时务必注意:
- 始终优先使用
yaml.safe_load() - 避免处理不可信的 YAML 源
- 合理使用高级特性以增强可维护性
掌握 PyYAML,能让你轻松应对配置管理、数据交换等常见任务,是 Python 开发者的实用工具之一。
参考资料:
- PyYAML 官方文档:https://pyyaml.org/
- GitHub 仓库:https://github.com/yaml/pyyaml
- YAML Specification: https://yaml.org/
更多推荐
所有评论(0)