大家好,我是jobleap.cn的小九。
Tomli 是 Python 生态中轻量、合规的 TOML 解析库,完全遵循 TOML 1.0.0 规范,仅专注于 TOML 数据的解析(写入需搭配 tomli-w),支持 Python 3.7+,纯 Python 实现且无第三方依赖。本教程将全面讲解 Tomli 的核心 API,通过实战案例串联所有常用用法,帮助你熟练掌握 TOML 解析技巧。
一、环境准备:安装 Tomli
首先通过 pip 安装 Tomli 库,命令如下:
pipinstalltomli验证安装是否成功:
importtomliprint(tomli.__version__)# 输出示例:2.0.1二、核心 API 总览
Tomli 的核心 API 极其简洁,核心包含2 个解析函数 + 1 个异常类:
| API 名称 | 作用 |
|---|---|
tomli.load(fp, **kwargs) | 从文件对象(file-like object)解析 TOML 数据,返回 Python 字典 |
tomli.loads(s, **kwargs) | 从字符串解析 TOML 数据,返回 Python 字典 |
tomli.TomliDecodeError | 解析过程中出现 TOML 语法错误时抛出的异常类 |
可选参数(kwargs)说明
parse_float:自定义浮点数解析函数(默认float)parse_int:自定义整数解析函数(默认int)parse_bool:自定义布尔值解析函数(默认bool)parse_datetime:自定义日期时间解析函数(默认datetime.datetime)
三、常用 API 实战详解
3.1 tomli.loads():解析 TOML 字符串
适用于从内存中的字符串解析 TOML 数据,是最基础的核心用法。
示例 1:解析基础数据类型(字符串/数字/布尔/日期时间)
Tomli 会自动将 TOML 类型映射为对应的 Python 类型,注释会被直接忽略:
importtomli# 定义包含基础类型的 TOML 字符串toml_str=""" # 这是注释(Tomli 会忽略) title = "Tomli Tutorial" version = 2.0.1 is_active = true release_date = 2025-12-10T10:00:00Z # TOML 标准日期时间格式 """# 解析字符串data=tomli.loads(toml_str)# 访问解析后的数据print("标题:",data["title"])# 输出:Tomli Tutorialprint("版本:",data["version"])# 输出:2.0.1print("是否激活:",data["is_active"])# 输出:Trueprint("发布时间:",data["release_date"])# 输出:2025-12-10 10:00:00+00:00print("时间类型:",type(data["release_date"]))# 输出:<class 'datetime.datetime'>示例 2:解析数组(列表)与嵌套数组
importtomli toml_str=""" # 简单字符串数组 fruits = ["apple", "banana", "orange"] # 混合数字数组 numbers = [1, 2, 3, 4.5] # 嵌套数组(二维矩阵) matrix = [[1, 2], [3, 4]] """data=tomli.loads(toml_str)print("水果列表:",data["fruits"])# 输出:['apple', 'banana', 'orange']print("数字数组:",data["numbers"])# 输出:[1, 2, 3, 4.5]print("嵌套数组:",data["matrix"])# 输出:[[1, 2], [3, 4]]示例 3:解析表(字典)与嵌套表
TOML 的「表」对应 Python 字典,支持多层嵌套和内联写法:
importtomli toml_str=""" # 基础表 [database] host = "127.0.0.1" port = 3306 user = "root" # 嵌套表 [database.connection] timeout = 30 charset = "utf8mb4" # 内联表(简洁写法) server = { ip = "192.168.1.1", port = 8080 } """data=tomli.loads(toml_str)print("数据库主机:",data["database"]["host"])# 输出:127.0.0.1print("连接超时:",data["database"]["connection"]["timeout"])# 输出:30print("服务器端口:",data["server"]["port"])# 输出:8080示例 4:解析数组表(表的数组)
适用于多个同结构的表(如列表式配置):
importtomli toml_str=""" # 数组表(多个用户配置) [[users]] name = "Alice" age = 25 [[users]] name = "Bob" age = 30 [[users]] name = "Charlie" age = 35 """data=tomli.loads(toml_str)# 遍历用户列表foruserindata["users"]:print(f"姓名:{user['name']},年龄:{user['age']}")# 输出:# 姓名:Alice,年龄:25# 姓名:Bob,年龄:30# 姓名:Charlie,年龄:353.2 tomli.load():解析 TOML 文件
当 TOML 数据存储在文件中时,使用load()更高效(直接读取文件对象解析)。
步骤 1:创建 TOML 配置文件(config.toml)
# 应用配置文件 [app] name = "MyApp" debug = false [app.log] level = "INFO" path = "./logs/app.log" [database] host = "localhost" port = 5432 dbname = "mydb" user = "postgres"步骤 2:使用 load() 解析文件
⚠️ 注意:必须以二进制模式(rb)打开文件(避免编码问题):
importtomli# 推荐使用 with 语句(自动关闭文件)withopen("config.toml","rb")asf:config=tomli.load(f)# 访问配置项print("应用名称:",config["app"]["name"])# 输出:MyAppprint("日志级别:",config["app"]["log"]["level"])# 输出:INFOprint("数据库名称:",config["database"]["dbname"])# 输出:mydb3.3 自定义解析函数(可选参数)
通过parse_*参数自定义解析逻辑,适用于特殊场景(如格式化数字、日期):
importtomli# 自定义浮点数解析:保留 2 位小数defcustom_parse_float(s):returnround(float(s),2)toml_str=""" pi = 3.1415926 price = 99.999 """# 传入自定义解析函数data=tomli.loads(toml_str,parse_float=custom_parse_float)print("圆周率:",data["pi"])# 输出:3.14print("价格:",data["price"])# 输出:100.03.4 异常处理(TomliDecodeError)
当 TOML 语法错误时,会抛出TomliDecodeError,需捕获并处理:
importtomlifromtomliimportTomliDecodeError# 错误的 TOML 字符串(缺少等号)invalid_toml=""" title "Tomli Tutorial" # 语法错误:key 后缺少 = """try:data=tomli.loads(invalid_toml)exceptTomliDecodeErrorase:print(f"解析失败:{e}")print(f"错误位置:行{e.lineno},列{e.colno}")# 输出示例:# 解析失败:Invalid statement at line 2, column 7: expected '=' after key# 错误位置:行 2,列 7四、综合实战:解析配置文件并应用
下面通过完整案例串联所有 API,实现「加载配置 → 验证配置 → 应用配置」的全流程。
4.1 编写配置文件(app_config.toml)
# 核心配置 [core] app_name = "DataProcessor" version = "1.0.0" enable_cache = true cache_ttl = 3600 # 数据源配置(数组表) [[datasources]] name = "mysql" type = "relational" config = { host = "127.0.0.1", port = 3306, db = "source_db", user = "root" } [[datasources]] name = "redis" type = "nosql" config = { host = "127.0.0.1", port = 6379, db = 0 } # 输出配置 [output] format = "json" path = "./output" compression = { enable = true, level = 6 }4.2 编写解析与应用代码
importtomlifromtomliimportTomliDecodeErrorimportosclassConfigLoader:"""配置加载器,封装 Tomli 解析逻辑"""def__init__(self,config_path):self.config_path=config_path self.config=Nonedefload_config(self):"""加载并解析 TOML 配置文件"""try:# 检查文件是否存在ifnotos.path.exists(self.config_path):raiseFileNotFoundError(f"配置文件{self.config_path}不存在")# 解析 TOML 文件withopen(self.config_path,"rb")asf:self.config=tomli.load(f)# 验证核心配置self._validate_core_config()print("配置加载并验证成功!")returnself.configexceptFileNotFoundErrorase:print(f"错误:{e}")returnNoneexceptTomliDecodeErrorase:print(f"配置语法错误:行{e.lineno},列{e.colno}→{e}")returnNoneexceptExceptionase:print(f"未知错误:{e}")returnNonedef_validate_core_config(self):"""验证核心配置项是否存在"""required_keys=["app_name","enable_cache"]forkeyinrequired_keys:ifkeynotinself.config.get("core",{}):raiseValueError(f"核心配置缺失:{key}")defget_datasource(self,name):"""根据名称获取数据源配置"""ifnotself.config:returnNonefordsinself.config.get("datasources",[]):ifds["name"]==name:returndsreturnNone# 实例化并加载配置config_loader=ConfigLoader("app_config.toml")config=config_loader.load_config()ifconfig:# 1. 打印核心配置print("\n=== 核心配置 ===")print(f"应用名称:{config['core']['app_name']}")print(f"是否启用缓存:{config['core']['enable_cache']}")# 2. 获取 MySQL 数据源配置print("\n=== MySQL 数据源 ===")mysql_ds=config_loader.get_datasource("mysql")ifmysql_ds:print(f"类型:{mysql_ds['type']}")print(f"主机:{mysql_ds['config']['host']}")# 3. 输出配置print("\n=== 输出配置 ===")print(f"格式:{config['output']['format']}")print(f"压缩级别:{config['output']['compression']['level']}")运行结果
配置加载并验证成功! === 核心配置 === 应用名称:DataProcessor 是否启用缓存:True === MySQL 数据源 === 类型:relational 主机:127.0.0.1 === 输出配置 === 格式:json 压缩级别:6五、常见问题与注意事项
- 编码要求:TOML 文件必须使用 UTF-8 编码,否则可能解析失败;
- 文件打开模式:
tomli.load()必须以rb(二进制)模式打开文件,避免编码冲突; - 类型映射:Tomli 严格遵循 TOML → Python 类型映射(如 TOML 日期时间 →
datetime.datetime); - 注释处理:解析结果中不会包含注释信息,Tomli 会直接忽略;
- 版本兼容:Tomli 2.x 仅支持 TOML 1.0.0,若需兼容旧版 TOML(0.5.x),请使用 Tomli 1.x。
六、扩展:TOML 写入(tomli-w)
Tomli 仅负责解析,若需生成 TOML 文件,可使用配套的tomli-w库:
pipinstalltomli-w示例:生成 TOML 文件
importtomli_w# 定义 Python 字典data={"title":"Tomli-W Demo","database":{"host":"localhost","port":3306}}# 写入 TOML 文件withopen("output.toml","wb")asf:tomli_w.dump(data,f)总结
Tomli 的核心 API 仅有load()(解析文件)和loads()(解析字符串),简洁易上手。通过本教程的实战案例,你已掌握基础类型解析、复杂结构解析、异常处理、自定义解析函数等所有常用用法。在实际项目中,Tomli 是处理 TOML 配置文件的首选库,配合tomli-w可完成 TOML 数据的「解析 + 生成」全流程。