1. YAML 概念
YAML (YAML Ain’t Markup Language) 是一種人性化的數據序列化格式:
- 專注于數據而非標記(與 XML 不同)
- 使用簡潔的語法表示復雜數據結構
- 可讀性高,適合人類編寫和閱讀
- 廣泛應用于配置文件(如 Docker Compose, Ansible, Kubernetes)
2. YAML 核心原理
- 縮進表示層級:類似 Python,使用空格縮進
- 最小化符號:避免引號、括號等干擾符號
- 數據類型推斷:自動識別數字、布爾值等類型
- 錨點與引用:支持數據復用(
&
定義錨點,*
引用) - 多文檔支持:單個文件可包含多個文檔(用
---
分隔)
3. YAML 語法規范
基本結構
# 注釋以 # 開頭
server: web01 # 鍵值對
ports:- 80 # 列表項- 443
environment: production
config:max_connections: 1000 # 嵌套對象timeout: 30
核心語法規則
- 縮進規則:
- 使用空格(不能使用 Tab)
- 同一層級縮進必須一致
- 數據類型:
- 字符串:可加引號也可不加(除非有特殊字符)
- 數字:整數(
42
)、浮點數(3.14
) - 布爾值:
true
/false
或yes
/no
- 空值:
null
或~
- 日期:
2023-11-15
(ISO 8601 格式)
- 數據結構:
- 列表(數組):使用
-
開頭 - 對象(字典):使用
key: value
格式
- 列表(數組):使用
- 多行文本:
description: |這是多行文本保留所有換行符summary: >這是折疊文本會合并為單行
- 特殊語法:
- 錨點
&name
和引用*name
- 合并
<<: *name
(合并映射)
- 錨點
4. Python YAML API (PyYAML)
安裝
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 處理流程
6. 應用示例
示例1:基本讀寫
輸入 (Python對象):
data = {"server": "web01","ports": [80, 443],"environment": "production","backup": True,"config": {"max_connections": 1000,"timeout": 30.5}
}
序列化 (Python → YAML):
import yaml# 轉換為YAML字符串
yaml_str = yaml.dump(data, indent=2)
print(yaml_str)
輸出 (YAML字符串):
server: web01
ports:
- 80
- 443
environment: production
backup: true
config:max_connections: 1000timeout: 30.5
反序列化 (YAML → Python):
# 從YAML字符串轉換回Python對象
loaded_data = yaml.safe_load(yaml_str)
print(loaded_data["ports"][0]) # 輸出: 80
示例2:文件操作
寫入YAML文件:
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:
database:host: db.example.comport: 3306user: adminpassword: secret
logging:level: debugpath: /var/log/app.log
讀取YAML文件:
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):
network:devices:- name: router01interfaces:- name: Gig0/0ip: 192.168.1.1mask: 255.255.255.0- name: Gig0/1ip: 10.0.0.1mask: 255.255.255.252ospf:enabled: trueareas: [0, 1]- name: switch01vlan:default: 1enabled: yes
Python解析代碼:
import yamlwith 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輸入:
defaults: &defaultsadapter: postgreshost: localhostport: 5432development:<<: *defaultsdatabase: dev_dbtest:<<: *defaultsdatabase: test_db
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):
---
server: web01
status: active
...
---
server: db01
status: maintenance
...
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. 安全注意事項
- 避免使用
yaml.load()
:可能執行任意代碼(使用safe_load
代替) - 驗證來源:不要加載不可信的 YAML 文件
- 自定義安全加載器:
from yaml import SafeLoaderclass RestrictedLoader(SafeLoader):pass# 禁用特定標簽 RestrictedLoader.add_constructor(None, None)
8. 常見錯誤處理
# 縮進錯誤示例
bad_yaml = """
server: web01ports: # 錯誤:不應縮進- 80
"""try:data = yaml.safe_load(bad_yaml)
except yaml.YAMLError as e:print(f"YAML解析錯誤: {e}")# 輸出: mapping values are not allowed here
9. 最佳實踐
- 字符串引號:當字符串包含
:
、#
等特殊字符時使用引號 - 列表縮進:列表項使用相同縮進
- 復雜結構:避免超過 4 層嵌套
- 行內風格:簡單結構可使用行內風格(如
ports: [80, 443]
) - 多文檔分隔:使用
---
分隔多個配置段 - 數據類型明確:對可能混淆的類型(如
yes
)添加類型標簽is_active: !!bool "yes" # 明確指定為布爾值
10. YAML 與其他格式對比
特性 | YAML | JSON | XML |
---|---|---|---|
可讀性 | ★★★★★ | ★★★☆☆ | ★★☆☆☆ |
簡潔性 | ★★★★★ | ★★★★☆ | ★☆☆☆☆ |
數據類型 | 豐富 | 基本 | 文本為主 |
注釋支持 | ? | ? | ? |
錨點引用 | ? | ? | ? |
學習曲線 | 低 | 低 | 中 |
總結
YAML 是自動化運維中最重要的配置文件格式之一,主要特點包括:
- 極高的可讀性和簡潔性
- 靈活的數據結構表示
- 支持復雜嵌套和引用
- 與腳本語言(如 Python)自然兼容
- 廣泛應用于 Ansible、Kubernetes、Docker 等工具
掌握 YAML 能幫助您高效處理各種配置管理任務,提升自動化運維效率。