YAML语法学习

YAML的全称是 “YAML Ain’t Markup Language”(YAML 不是一种标记语言)。它是一种以数据为中心、面向人类的数据序列化格式,设计上追求简洁和强大,常被用作配置文件(如Docker Compose、Kubernetes)或数据交换语言。它的语法非常直观,使用缩进来表示层级,因此学习起来并不困难。

YAML的全称是 “YAML Ain’t Markup Language”(YAML 不是一种标记语言)。它是一种以数据为中心、面向人类的数据序列化格式,设计上追求简洁和强大,常被用作配置文件(如Docker Compose、Kubernetes)或数据交换语言。它的语法非常直观,使用缩进来表示层级,因此学习起来并不困难。

📖 YAML语法详解

YAML的核心在于用它提供的几种数据类型来表达各种复杂的数据结构。

1. 基础语法规则

  • 大小写敏感,并使用缩进来表示层级关系。
  • 缩进必须使用空格,不能使用Tab键。推荐使用2个空格作为一级缩进。
  • # 符号添加注释,注释会被解析器忽略。
  • 一份YAML文件可以由一个或多个文档组成,文档之间用 ---(三个横线)分隔。

2. 数据类型

  • 标量 (Scalars): 最简单的、不可再分的单个值,比如字符串、数字、布尔值、Null等。

    1
    2
    3
    4
    5
    6
    7
    name: John Doe       # 字符串(通常可省略引号)
    age: 30 # 整数
    score: 99.5 # 浮点数
    is_active: true # 布尔值
    email: john@example.com
    special_str: "包含: 冒号等特殊字符时才需要引号"
    empty_value: null # 空值
  • 映射 (Mappings): 即键值对集合,类似Python中的字典(Dict) 或JSON对象。键和值用 : 和一个空格分隔(冒号后面必须有一个空格),通过缩进来表示嵌套。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 简单的键值对
    name: Alice
    age: 30

    # 嵌套结构
    address:
    street: 123 Main St
    city: Anytown
    zip: "12345"
  • 序列 (Sequences): 有序列表,类似Python中的列表(List) 或JSON数组。每个元素以 - 和一个空格开头。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # 简单列表
    hobbies:
    - reading
    - hiking
    - coding

    # 混合类型列表
    mixed_list:
    - Hello
    - 42
    - true
  • 复合结构: 映射和序列可以任意嵌套,形成复杂的树状结构。

    1
    2
    3
    4
    5
    6
    7
    8
    # 一个列表,其中的每个元素都是一个映射
    employees:
    - name: John Doe
    age: 30
    title: Engineer
    - name: Jane Smith
    age: 25
    title: Designer
  • 高级技巧:锚点 (&) 与别名 (*)

    • 使用 & 定义一个可重用的“锚点”片段,然后用 * 在其它地方创建引用它的“别名”。这能有效避免重复,精简配置。
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      # 定义一个名为 'default_user' 的锚点
      user_defaults: &default_user
      name: Unknown
      email: placeholder@example.com
      is_active: false

      # 在其他地方使用别名 *default_user 引用它
      user_one:
      <<: *default_user # 使用 << 合并键,将 default_user 的内容合并进来
      name: Bob # 覆盖 name 属性
      # email 和 is_active 属性会继承自锚点

      user_two:
      <<: *default_user
      email: alice@example.com
      is_active: true # 覆盖 is_active 属性

🐍 Python调用YAML文件实战

在Python中,最主流的YAML处理库是 PyYAMLruamel.yaml,推荐使用 PyYAML 入门。

1. 安装与准备

首先需要安装 PyYAML 库。确保你的网络环境正常,然后在终端(命令行)执行以下命令:

1
pip install pyyaml

注意:库的包名是 pyyaml,但在Python代码中引入时,使用的是 import yaml

2. 读取 (Load) YAML文件

这是最常用的操作,将YAML内容解析为Python对象(通常是字典 dict 或列表 list)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import yaml

# 假设我们有一个名为 'config.yaml' 的文件,内容如下:
# database:
# host: localhost
# port: 5432
# user: admin
# password: secret

with open('config.yaml', 'r', encoding='utf-8') as file:
config = yaml.safe_load(file)
# 使用 safe_load 是更安全的做法,可以防止执行YAML文件中可能存在的恶意代码

# 现在 config 是一个 Python 字典,可以直接使用
print(config['database']['host']) # 输出: localhost
print(config['database']['port']) # 输出: 5432
  • 关键点: yaml.safe_load 是推荐的安全解析方式,直接将文件内容转换Python字典。
  • 从字符串加载: 除了文件,yaml.safe_load 也可直接解析YAML格式的字符串。

3. 写入 (Dump) 为YAML文件

将Python对象(字典、列表等)序列化并保存为YAML文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import yaml

data = {
'server': {
'host': '192.168.1.100',
'port': 8080,
'ssl': True
},
'users': ['alice', 'bob', 'charlie']
}

with open('output.yaml', 'w', encoding='utf-8') as file:
# 将 Python 对象写入 YAML 文件
# default_flow_style=False 让输出更易读(使用块风格而非流式风格)
yaml.dump(data, file, default_flow_style=False, sort_keys=False, allow_unicode=True)

# 常用参数说明:
# - default_flow_style=False: 使用缩进块风格(更可读)而非内联风格
# - sort_keys=False: 保持字典键的原始顺序(默认会按字母排序)
# - allow_unicode=True: 确保文件中的中文字符能正常显示

4. jinja2 与 YAML 结合

YAML 和 Jinja2 结合的核心思想是 数据与逻辑分离:YAML 负责存储静态数据结构,Jinja2 负责动态生成最终内容。

示例场景

根据 YAML 定义的服务器列表,生成 Nginx 配置文件片段。

  1. YAML 数据文件 (servers.yaml)
1
2
3
4
5
6
7
8
servers:
- name: web1
ip: 192.168.1.10
port: 80
- name: web2
ip: 192.168.1.11
port: 80
upstream_name: backend
  1. Jinja2 模板 (nginx_upstream.j2)
1
2
3
4
5
upstream {{ upstream_name }} {
{% for server in servers %}
server {{ server.ip }}:{{ server.port }}; # {{ server.name }}
{% endfor %}
}
  1. Python 渲染脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import yaml
from jinja2 import Template

# 1. 读取 YAML
with open('servers.yaml', encoding='utf-8') as f:
data = yaml.safe_load(f)

# 2. 加载 Jinja2 模板
with open('nginx_upstream.j2', encoding='utf-8') as f:
template = Template(f.read())

# 3. 渲染输出
output = template.render(data)
print(output)
  1. 输出结果
1
2
3
4
upstream backend {
server 192.168.1.10:80; # web1
server 192.168.1.11:80; # web2
}

优点:数据修改无需动模板,易于维护和版本控制。

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2019-2026 Vincere Zhou
  • 访问人数: | 浏览次数:

请我喝杯茶吧~

支付宝
微信