以下是关于 YAML 文件及 Python 解析的详细指南,涵盖基础到进阶用法,并提供实际案例和注意事项:
一、YAML 文件基础
1. YAML 语法特点
- 键值对:使用缩进表示层级关系(类似 Python)。
- 列表:用
-
表示列表项。 - 多行文本:用
|
(保留换行)或>
(折叠换行)。 - 注释:以
#
开头。 - 数据类型:自动识别字符串、布尔值、整数、浮点数、
null
等。
2. 示例 YAML 文件 (config.yaml
)
app:
name: MyApp
version: 1.0.0
debug: false
database:
host: db.example.com
port: 5432
credentials:
username: admin
password: "1234!@#$" # 特殊字符需加引号
features:
- logging
- auth
- api
二、Python 解析 YAML 的完整流程
1. 安装 PyYAML
pip install pyyaml
2. 基础解析示例
import yaml
# 读取并解析 YAML
with open("config.yaml", "r") as file:
config = yaml.safe_load(file) # 安全解析方法
# 访问嵌套数据
print(config["app"]["name"]) # 输出: MyApp
print(config["app"]["database"]["host"]) # 输出: db.example.com
print(config["app"]["features"][0]) # 输出: logging
3. 处理复杂结构
场景:解析包含多文档的 YAML
# multi_doc.yaml
---
user: Alice
role: admin
---
user: Bob
role: guest
with open("multi_doc.yaml", "r") as file:
docs = list(yaml.safe_load_all(file)) # 解析多个文档
for doc in docs:
print(f"User: {doc['user']}, Role: {doc['role']}")
三、高级用法与技巧
1. 自定义解析(处理特殊类型)
如果 YAML 中包含日期等复杂类型:
from datetime import datetime
# 确保日期解析正确
def parse_datestamp(loader, node):
value = loader.construct_scalar(node)
return datetime.strptime(value, "%Y-%m-%d %H:%M:%S")
yaml.SafeLoader.add_constructor("tag:yaml.org,2002:timestamp", parse_datestamp)
with open("event.yaml") as file:
data = yaml.safe_load(file)
print(data["event"]["time"].isoformat()) # 输出: 2023-10-05T14:30:00
2. 生成 YAML 文件(保留格式)
import yaml
data = {
"server": {
"ports": [80, 443],
"environment": "production",
"metadata": {"owner": "Team A", "priority": 1}
}
}
with open("output.yaml", "w") as file:
yaml.dump(data, file, sort_keys=False, default_flow_style=False)
生成 output.yaml
:
server:
ports:
- 80
- 443
environment: production
metadata:
owner: Team A
priority: 1
3. 使用 ruamel.yaml
保留注释和格式
from ruamel.yaml import YAML
yaml = YAML()
yaml.preserve_quotes = True # 保留字符串引号
# 读取并修改 YAML
with open("config.yaml") as file:
data = yaml.load(file)
data["app"]["version"] = "2.0.0"
# 写回文件(保留原始格式)
with open("config_updated.yaml", "w") as file:
yaml.dump(data, file)
四、常见问题与解决方案
1. 编码问题
- 现象:解析时出现
UnicodeDecodeError
。 - 解决:指定文件编码:
with open("config.yaml", "r", encoding="utf-8") as file: data = yaml.safe_load(file)
2. 安全性问题
- 风险:
yaml.load()
可能执行恶意代码。 - 强制规范:始终使用
yaml.safe_load()
或自定义 Loader。
3. 处理大文件
- 优化:逐块解析(适合日志类 YAML):
with open("large_file.yaml") as file: for chunk in yaml.safe_load_all(file): process(chunk) # 分块处理
4. 数据验证
使用 pydantic
或 marshmallow
验证解析后的数据:
from pydantic import BaseModel
class DatabaseConfig(BaseModel):
host: str
port: int
username: str
password: str
# 解析后验证
db_config = DatabaseConfig(**config["app"]["database"])
五、实际应用场景
1. 配置文件管理
- 将应用配置(数据库、API 密钥)存储在 YAML 中,通过 Python 动态加载。
2. 数据序列化
- 替代 JSON,用于需要人类可读性的场景(如测试数据存储)。
3. CI/CD 流程
- 解析 GitHub Actions 或 GitLab CI 的 YAML 配置进行自动化检查。