python 3.11+ 内置 tomllib,旧版本需用 tomli;兼容写法为 try/except 导入后统一 alias 为 toml;异常需全路径捕获,文件读取须显式指定 encoding='utf-8';tomli 支持 parse_float,tomllib 不支持。

tomllib 在 Python 3.11+ 是标准库,但旧版本必须用 tomli
Python 3.11 开始内置 tomllib,名字和行为都刻意对标第三方 tomli;但如果你在 3.10 或更早版本里写 import tomllib,会直接报 ModuleNotFoundError: No module named 'tomllib'。这不是拼错,是真没有。
实操建议:
- 检查 Python 版本:运行
python -c "import sys; print(sys.version)" - 3.11+:优先用
tomllib(无需安装) - 3.10 及以下:装
tomli(pip install tomli),代码里写import tomli - 想一份代码兼容所有版本?用
try/except导入,再统一 alias 成toml
tomli 和 tomllib 的 load() / loads() 行为几乎一致,但错误类型不同
两者 API 高度对齐:load() 读文件对象,loads() 读字符串,返回都是 dict。但抛出的异常类型不兼容——tomli 抛 tomli.TOMLDecodeError,tomllib 抛 tomllib.TOMLDecodeError。如果代码里写了 except TOMLDecodeError: 却没从对应模块 import,就会报 NameError。
常见错误现象:本地跑得好,CI 上失败,只因 CI 用的是不同 Python 版本。
立即学习“Python免费学习笔记(深入)”;
实操建议:
- 不要裸写
except TOMLDecodeError,显式写全路径:except tomli.TOMLDecodeError:或except tomllib.TOMLDecodeError: - 若需统一处理,捕获
Exception并检查isinstance(e, (tomli.TOMLDecodeError, tomllib.TOMLDecodeError)) -
loads()对非法字符串(如空字符串、纯注释)的行为一致,但错误信息细节略有差异,别依赖 message 正则匹配
Windows 下路径含中文时,tomllib 会因编码隐式失败
tomllib.load() 接收的是文件对象,它不负责解码——你传进去的 open('配置.toml', 'r') 如果没指定 encoding,在 Windows 默认 CP1252 编码下读中文会直接 UnicodeDecodeError。这不是 TOML 解析器的问题,是 Python 文件打开逻辑的坑。
使用场景:配置文件名或路径含中文,或文件本身是 UTF-8 但没声明 BOM(Windows 记事本常干这事)。
实操建议:
- 始终显式指定 encoding:
open('配置.toml', 'r', encoding='utf-8') - 避免用
pathlib.Path.open()不带参数的方式,它默认继承系统 locale 编码 - 如果必须支持无 BOM 的 UTF-8 + 中文路径,加
errors='replace'保底,但会破坏原始内容
tomli 0.12.0+ 支持 parse_float,但 tomllib 没这个参数
有些场景需要把浮点数转成 decimal.Decimal 或自定义数值类型(比如财务计算防精度丢失),tomli.load() 自 0.12.0 起支持 parse_float=Decimal 参数;而 tomllib 完全不支持该参数,传了就报 TypeError: load() got an unexpected keyword argument 'parse_float'。
性能影响:启用 parse_float 后解析速度下降约 15–20%,但换来的是可控的数值类型。
实操建议:
- 业务强依赖自定义浮点解析?放弃
tomllib,统一用tomli(哪怕在 3.11+ 也 pip install tomli) - 若只是偶尔需要,封装一层适配函数,对
tomllib做 post-process(遍历 dict 找float类型再转换) - 别试图 monkey patch
tomllib——它底层是 C 实现,不可动态注入
最易被忽略的一点:TOML 规范允许键名含点号(foo.bar = 1),但 Python 字典访问时不能写 d.foo.bar;很多人误以为解析器该返回 object-like 结构,其实不会——无论 tomli 还是 tomllib,都只返回嵌套 dict,这点从不越界。










