PyYAML默认启用安全模式,需显式指定CSafeLoader;dump时中文乱码、None变null、时间格式固定、不保留空行注释缩进,需配置allow_unicode、default_flow_style等参数;锚点引用等高级特性需ruamel.yaml。

PyYAML读取嵌套字典时,yaml.load()直接报错
默认情况下,yaml.load() 会拒绝解析任意 YAML 标签(比如 !ref、!!python/object),遇到就抛 ParserError 或 ConstructorError。这不是你 YAML 写错了,是 PyYAML 5.1+ 默认启用了“安全子集”模式 —— 但这个“安全”其实是指“不执行任意代码”,不是指“不报错”。
- 必须显式传入
Loader=yaml.CSafeLoader(推荐)或Loader=yaml.SafeLoader,否则老版本写法在新环境直接崩 -
CSafeLoader比SafeLoader快,且行为一致,只要 C 扩展可用就优先用它 - 别用
yaml.FullLoader或yaml.UnsafeLoader,除非你完全信任输入源 —— 配置文件被注入恶意标签可导致任意代码执行
正确写法:
import yaml<br>with open("config.yaml") as f:<br> data = yaml.load(f, Loader=yaml.CSafeLoader)
用yaml.dump()保存带中文、时间、None的配置,输出乱码或变成null
PyYAML 默认把 None 转成 null,把 datetime 对象转成 ISO 字符串(但没加引号),中文则可能被转成 Unicode 转义(如 \u4f60\u597d)—— 这些都不是 bug,是默认行为。
- 加
allow_unicode=True让中文原样输出,不转义 - 加
default_flow_style=False避免把小字典压成一行,提升可读性 -
None会变成null,这是 YAML 规范行为;如果想存成空字符串或占位符,得提前遍历替换,PyYAML 不提供“null → empty string”开关 - 时间对象会被序列化,但若需自定义格式(比如只留日期),得注册自己的
Representer,不能靠参数控制
常用组合:
yaml.dump(data, stream=f, allow_unicode=True, default_flow_style=False, sort_keys=False)(
sort_keys=False 防止字段顺序被重排)立即学习“Python免费学习笔记(深入)”;
修改嵌套字典后,用yaml.dump()保存,层级缩进错乱或丢失空行
PyYAML 不保留原始 YAML 的空行、注释和缩进风格 —— 它只管数据结构,不管“怎么写得好看”。所以你读进来改完再 dump,得到的是规范但“冷冰冰”的输出。
- 没有内置方式保留注释或空行;真要维持编辑体验,得换库(如
ruamel.yaml),但那就不是纯 PyYAML 了 - 缩进由
indent参数控制,默认是 2,设成 4 就变 4 空格:indent=4 - 嵌套太深时,PyYAML 可能自动切到 flow style(即
{key: val}形式),加default_flow_style=False强制 block style - 如果 dump 出来字段顺序和源文件不一致,是因为 Python dict 在 3.7+ 虽保持插入序,但如果你用的是旧版或手动构造 dict,顺序仍可能乱 —— 用
collections.OrderedDict或确保 Python ≥ 3.7
从文件读取后修改某一层级值,再保存,结果整个配置被重写,原有结构语义丢失
典型场景:你读 config.yaml,改了 data["database"]["port"],然后 dump 回去 —— 表面看没问题,但若原始文件用了锚点(&common)、引用(*common)或自定义类型,这些全没了。
- PyYAML 解析后,锚点/引用已被展开为普通数据结构,dump 时不可能还原
- 自定义 tag(如
!include)不会被识别,除非你手动注册Constructor,而 dump 更不会生成它们 - 所谓“层级配置项”只是嵌套 dict,PyYAML 不知道哪层该叫“服务配置”,哪层是“全局开关” —— 它只认数据,不认业务语义
- 如果必须保留锚点、引用、注释等,
ruamel.yaml是唯一靠谱选择,但它不是 PyYAML 的替代品,而是另一个库
简单说:PyYAML 是“数据管道”,不是“配置编辑器”。你要它读写结构化数据,没问题;指望它理解配置意图、保留格式细节,就超纲了。


















