Python 读取 YAML:safe_load 和转对象访问

Python 里读 YAML 配置文件,标准做法就是 PyYAML

安装

pip install pyyaml

示例配置

config.yaml

server:
  host: 127.0.0.1
  port: 8000

database:
  user: root
  password: 123456

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,别用 yaml.loadsafe_load 拒绝任意 Python 对象反序列化,避开加载不受信配置时的 RCE 风险。

转对象访问(少写引号)

字典下标写多了嫌烦,可以套一层 SimpleNamespace

from types import SimpleNamespace
import yaml

with open("config.yaml", encoding="utf-8") as f:
    data = yaml.safe_load(f)

cfg = SimpleNamespace(**data)
print(cfg.server)     # 但 cfg.server 还是 dict

只包一层不够——嵌套的字典还得递归转:

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:
    cfg = to_obj(yaml.safe_load(f))

print(cfg.server.host)      # 127.0.0.1
print(cfg.database.user)    # root

工程项目更推荐用 pydantic.BaseModeldataclass——能顺带做类型校验:

from pydantic import BaseModel
import yaml

class ServerCfg(BaseModel):
    host: str
    port: int

class Config(BaseModel):
    server: ServerCfg
    names: list[str]

with open("config.yaml", encoding="utf-8") as f:
    cfg = Config(**yaml.safe_load(f))

print(cfg.server.host)

输出 YAML

反向写文件同样常用:

import yaml

data = {"server": {"host": "0.0.0.0", "port": 80}}

with open("out.yaml", "w", encoding="utf-8") as f:
    yaml.safe_dump(data, f, allow_unicode=True, sort_keys=False)
  • allow_unicode=True 中文不会变成 \uXXXX
  • sort_keys=False 保持字段顺序

一句话总结

yaml.safe_load(open(..., encoding="utf-8")) 起步,需要结构化访问就 pydantic。写回用 safe_dump + allow_unicode=True