YAML 数据格式详解

1. YAML 概念

YAML (YAML Ain't Markup Language) 是一种人性化的数据序列化格式:

  • 专注于数据而非标记(与 XML 不同)
  • 使用简洁的语法表示复杂数据结构
  • 可读性高,适合人类编写和阅读
  • 广泛应用于配置文件(如 Docker Compose, Ansible, Kubernetes)

2. YAML 核心原理

  • 缩进表示层级:类似 Python,使用空格缩进
  • 最小化符号:避免引号、括号等干扰符号
  • 数据类型推断:自动识别数字、布尔值等类型
  • 锚点与引用 :支持数据复用(& 定义锚点,* 引用)
  • 多文档支持 :单个文件可包含多个文档(用 --- 分隔)

3. YAML 语法规范

基本结构

yaml 复制代码
# 注释以 # 开头
server: web01  # 键值对
ports:
  - 80        # 列表项
  - 443
environment: production
config:
  max_connections: 1000  # 嵌套对象
  timeout: 30

核心语法规则

  1. 缩进规则

    • 使用空格(不能使用 Tab)
    • 同一层级缩进必须一致
  2. 数据类型

    • 字符串:可加引号也可不加(除非有特殊字符)
    • 数字:整数(42)、浮点数(3.14
    • 布尔值:true/falseyes/no
    • 空值:null~
    • 日期:2023-11-15(ISO 8601 格式)
  3. 数据结构

    • 列表(数组):使用 - 开头
    • 对象(字典):使用 key: value 格式
  4. 多行文本

    yaml 复制代码
    description: |
      这是多行文本
      保留所有换行符
      
    summary: >
      这是折叠文本
      会合并为单行
  5. 特殊语法

    • 锚点 &name 和引用 *name
    • 合并 <<: *name(合并映射)

4. Python YAML API (PyYAML)

安装

bash 复制代码
pip install pyyaml

核心功能

函数 功能 主要参数
yaml.safe_load() 安全解析 YAML stream(文件或字符串)
yaml.load() 解析 YAML(不安全) stream, Loader
yaml.safe_dump() 安全序列化为 YAML data, stream, indent
yaml.dump() 序列化为 YAML data, default_flow_style

关键参数

  • dump/dump_all
    • indent:缩进空格数
    • default_flow_style:是否使用流式风格(默认 False)
    • allow_unicode:是否允许 Unicode 字符
    • sort_keys:是否按键排序
  • load/load_all
    • Loader:指定加载器(推荐 yaml.SafeLoader

5. YAML 处理流程

yaml.dump yaml.safe_load yaml.dump yaml.safe_load yaml.dump_all yaml.safe_load_all Python对象 YAML字符串 Python对象 YAML文件 多文档数据 多文档YAML

6. 应用示例

示例1:基本读写

输入 (Python对象):

python 复制代码
data = {
    "server": "web01",
    "ports": [80, 443],
    "environment": "production",
    "backup": True,
    "config": {
        "max_connections": 1000,
        "timeout": 30.5
    }
}

序列化 (Python → YAML):

python 复制代码
import yaml

# 转换为YAML字符串
yaml_str = yaml.dump(data, indent=2)
print(yaml_str)

输出 (YAML字符串):

yaml 复制代码
server: web01
ports:
- 80
- 443
environment: production
backup: true
config:
  max_connections: 1000
  timeout: 30.5

反序列化 (YAML → Python):

python 复制代码
# 从YAML字符串转换回Python对象
loaded_data = yaml.safe_load(yaml_str)
print(loaded_data["ports"][0])  # 输出: 80

示例2:文件操作

写入YAML文件:

python 复制代码
config = {
    "database": {
        "host": "db.example.com",
        "port": 3306,
        "user": "admin",
        "password": "secret"
    },
    "logging": {
        "level": "debug",
        "path": "/var/log/app.log"
    }
}

with open("config.yaml", "w") as f:
    yaml.dump(config, f, indent=4, default_flow_style=False)

生成的config.yaml:

yaml 复制代码
database:
    host: db.example.com
    port: 3306
    user: admin
    password: secret
logging:
    level: debug
    path: /var/log/app.log

读取YAML文件:

python 复制代码
with open("config.yaml", "r") as f:
    loaded_config = yaml.safe_load(f)
    print(loaded_config["database"]["host"])  # 输出: db.example.com

示例3:复杂结构处理

YAML输入 (network.yaml):

yaml 复制代码
network:
  devices:
    - name: router01
      interfaces:
        - name: Gig0/0
          ip: 192.168.1.1
          mask: 255.255.255.0
        - name: Gig0/1
          ip: 10.0.0.1
          mask: 255.255.255.252
      ospf:
        enabled: true
        areas: [0, 1]
    - name: switch01
      vlan:
        default: 1
        enabled: yes

Python解析代码:

python 复制代码
import yaml

with open("network.yaml") as f:
    data = yaml.safe_load(f)

for device in data["network"]["devices"]:
    print(f"设备: {device['name']}")
    if "interfaces" in device:
        for interface in device["interfaces"]:
            print(f"  接口: {interface['name']}, IP: {interface['ip']}")

输出:

复制代码
设备: router01
  接口: Gig0/0, IP: 192.168.1.1
  接口: Gig0/1, IP: 10.0.0.1
设备: switch01

示例4:锚点与引用

YAML输入:

yaml 复制代码
defaults: &defaults
  adapter: postgres
  host: localhost
  port: 5432

development:
  <<: *defaults
  database: dev_db

test:
  <<: *defaults
  database: test_db

Python解析后:

python 复制代码
{
    'defaults': {
        'adapter': 'postgres',
        'host': 'localhost',
        'port': 5432
    },
    'development': {
        'adapter': 'postgres',
        'host': 'localhost',
        'port': 5432,
        'database': 'dev_db'
    },
    'test': {
        'adapter': 'postgres',
        'host': 'localhost',
        'port': 5432,
        'database': 'test_db'
    }
}

示例5:多文档处理

YAML输入 (multi_doc.yaml):

yaml 复制代码
---
server: web01
status: active
...
---
server: db01
status: maintenance
...

Python读取多文档:

python 复制代码
with open("multi_doc.yaml") as f:
    documents = list(yaml.safe_load_all(f))

for doc in documents:
    print(f"服务器: {doc['server']}, 状态: {doc['status']}")

输出:

复制代码
服务器: web01, 状态: active
服务器: db01, 状态: maintenance

7. 安全注意事项

  1. 避免使用 yaml.load() :可能执行任意代码(使用 safe_load 代替)

  2. 验证来源:不要加载不可信的 YAML 文件

  3. 自定义安全加载器

    python 复制代码
    from yaml import SafeLoader
    
    class RestrictedLoader(SafeLoader):
        pass
    
    # 禁用特定标签
    RestrictedLoader.add_constructor(None, None)

8. 常见错误处理

python 复制代码
# 缩进错误示例
bad_yaml = """
server: web01
  ports:  # 错误:不应缩进
    - 80
"""

try:
    data = yaml.safe_load(bad_yaml)
except yaml.YAMLError as e:
    print(f"YAML解析错误: {e}")
    # 输出: mapping values are not allowed here

9. 最佳实践

  1. 字符串引号 :当字符串包含 :# 等特殊字符时使用引号

  2. 列表缩进:列表项使用相同缩进

  3. 复杂结构:避免超过 4 层嵌套

  4. 行内风格 :简单结构可使用行内风格(如 ports: [80, 443]

  5. 多文档分隔 :使用 --- 分隔多个配置段

  6. 数据类型明确 :对可能混淆的类型(如 yes)添加类型标签

    yaml 复制代码
    is_active: !!bool "yes"  # 明确指定为布尔值

10. YAML 与其他格式对比

特性 YAML JSON XML
可读性 ★★★★★ ★★★☆☆ ★★☆☆☆
简洁性 ★★★★★ ★★★★☆ ★☆☆☆☆
数据类型 丰富 基本 文本为主
注释支持
锚点引用
学习曲线

总结

YAML 是自动化运维中最重要的配置文件格式之一,主要特点包括:

  • 极高的可读性和简洁性
  • 灵活的数据结构表示
  • 支持复杂嵌套和引用
  • 与脚本语言(如 Python)自然兼容
  • 广泛应用于 Ansible、Kubernetes、Docker 等工具

掌握 YAML 能帮助您高效处理各种配置管理任务,提升自动化运维效率。

相关推荐
微信公众号:AI创造财富10 分钟前
构建 docket uable to prepar context: path “.“ not found
python·plotly·flask·pillow·ipython·tornado
烛阴17 分钟前
Python多进程开发实战:轻松突破GIL瓶颈
前端·python
Sim time28 分钟前
用AI从0开始量化交易-Anaconda环境(env)和缓存(pkg)更改储存位置
人工智能·python·conda
struggle202543 分钟前
torchmd-net开源程序是训练神经网络潜力
c++·人工智能·python·深度学习·神经网络
软件开发技术深度爱好者1 小时前
python中学物理实验模拟:凸透镜成像和凹透镜成像
开发语言·python
PHP武器库1 小时前
想学编程,java,python,php先学哪个比较好?
java·python·php
鱼鱼说测试1 小时前
jmeter工具简单认识
开发语言·python
网小鱼的学习笔记2 小时前
flask静态资源与模板页面、模板用户登录案例
后端·python·flask
aiweker2 小时前
python web开发-Flask数据库集成
前端·python·flask
weixin_307779133 小时前
Python实现MySQL建表语句转换成Clickhouse SQL
数据库·python·sql·mysql·clickhouse