Python 读写 YAML 文件用 PyYAML,核心只有两个函数:yaml.safe_load 和 yaml.dump。
安装
pip install pyyaml
读取 YAML
# config.yaml
server:
host: 127.0.0.1
port: 8000
database:
user: root
password: secret123
names:
- alice
- bob
import yaml
with open("config.yaml", "r", encoding="utf-8") as f:
data = yaml.safe_load(f)
print(data["server"]["host"]) # 127.0.0.1
print(data["names"]) # ['alice', 'bob']
用 safe_load 而不是 load——load 会执行 YAML 里嵌入的 Python 代码,存在安全风险。
写出 YAML
import yaml
data = {
"server": {"host": "127.0.0.1", "port": 8000},
"database": {"user": "root", "password": "secret123"},
"names": ["alice", "bob"]
}
with open("output.yaml", "w", encoding="utf-8") as f:
yaml.dump(
data,
f,
allow_unicode=True, # 中文不转成 \uXXXX
sort_keys=False # 保持原字典顺序
)
默认 sort_keys=True,会按字母排序;allow_unicode=False 会把中文转成 \uXXXX——一般都要加这两个参数。
输出为字符串
yaml_str = yaml.dump(data, allow_unicode=True, sort_keys=False)
print(yaml_str)
修改 YAML 文件(读取后更新)
import yaml
with open("config.yaml", encoding="utf-8") as f:
cfg = yaml.safe_load(f)
cfg["server"]["port"] = 9000
cfg["names"].append("carol")
with open("config.yaml", "w", encoding="utf-8") as f:
yaml.dump(cfg, f, allow_unicode=True, sort_keys=False)
转成对象访问(点号语法)
如果不喜欢 data["server"]["host"],可以转成 SimpleNamespace:
from types import SimpleNamespace
import yaml
def to_obj(d):
if isinstance(d, dict):
return SimpleNamespace(**{k: to_obj(v) for k, v in d.items()})
if isinstance(d, list):
return [to_obj(i) for i in d]
return d
with open("config.yaml", encoding="utf-8") as f:
config = to_obj(yaml.safe_load(f))
print(config.server.host) # 127.0.0.1
print(config.database.user) # root
常见坑
名称含冒号的字符串要加引号,否则 YAML 解析出错:
# 错误
name: O:
# 正确
name: "O:"
字段名问题:Clash Meta 等工具要求字段名是 port,不能是 server_port。读取 sing-box 格式(用 server_port)再写入 Clash 配置时记得手动映射:
clash_node = {
"name": node["tag"],
"server": node["server"],
"port": node["server_port"], # 注意字段名
"type": node["type"],
}
直接 yaml.dump(singbox_node) 生成的字段名 Clash 不认,会报 has unset fields: port。
