什么是 TOML?零基础也能看懂的配置文件格式入门指南

原创 发布日期:
24

一、TOML 是什么?一句话讲清楚

TOML,全称 Tom's Obvious, Minimal Language(汤姆的明显最小化语言),由 GitHub 联合创始人 Tom Preston-Werner 于 2013 年创建。它的设计目标只有一个:让配置文件既能被人轻松读懂,又能被机器精确解析,且无歧义地映射为哈希表。

你可以把它理解为一种"升级版的 INI 文件"——它保留了 INI 的简洁,却支持嵌套结构、数组、日期时间等复杂数据类型,同时比 JSON 多了注释功能,比 YAML 少了缩进带来的歧义。

TOML 已成为众多主流工具的首选配置格式

  • Python 项目的 pyproject.toml(Poetry、Flit 等包管理工具)

  • Rust 项目的 Cargo.toml(官方包管理配置)

  • Hugo 静态网站生成器、GitHub Actions 工作流等

二、为什么选择 TOML?三大核心优势

特性 TOML JSON YAML
支持注释 ✅ 支持 # 注释 ❌ 不支持 ✅ 支持
语法简洁度 键值对,无多余符号 大量 {} [] "" 缩进敏感,容易出错
数据类型丰富度 字符串/数字/布尔/日期/数组/表 仅6种基础类型 丰富但有歧义
人类可读性 ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐
无歧义映射 ✅ 严格映射哈希表 ⚠️ 缩进可能产生歧义

TOML 的三大核心优势

  1. 直观易读:采用类 INI 文件的结构,语法简洁明了,非技术人员也能轻松理解

  2. 无歧义映射:严格的语法规则确保配置文件能唯一映射到哈希表结构,不会出现"同一份配置解析出不同结果"的情况

  3. 多语言支持:几乎所有主流编程语言都有成熟的 TOML 解析库(Python、Rust、Go、JavaScript 等)

三、TOML 基础语法:从键值对开始

TOML 文件的最基本构成单元是键值对(Key = Value),格式为 key = value

name = "MyApp"
version = "1.0.0"
enabled = true

核心规则

  • 键和等号之间允许有空格,等号和值之间也允许有空格,空格会被忽略

  • 键值对必须写在同一行,不能跨行

  • 每个键值对后必须换行或结束文件

  • TOML 大小写敏感Namename 是两个不同的键

键名的三种形式

键名类型 示例 说明
裸键(Bare Key)server_port = 8080 只能包含字母、数字、下划线、短横线
引号键(Quoted Key)"server address" = "192.168.1.1" 支持空格、特殊字符、中文
点分隔键(Dot Key)physical.color = "orange" 等价于 [physical] color = "orange"

四、TOML 支持的数据类型(重点)

这是 TOML 最强大的地方——它原生支持丰富的数据类型,不像 JSON 那样一切都是字符串或数字。

1. 字符串:四种写法,应对所有场景

类型 语法 示例 适用场景
基本字符串 双引号 ""Hello\nWorld" 需要转义字符时
多行基本字符串 三个双引号 """"""Line1\nLine2""" 多行文本
字面量字符串 单引号 ''C:\Users\Tom'路径、正则表达式(不转义)
多行字面量字符串 三个单引号 ''''''多行代码''' 代码块、脚本

关键区别:字面量字符串(单引号)不处理任何转义字符,所见即所得。 这对于写 Windows 路径极其友好:

# 推荐:字面量字符串,反斜杠不会被转义
path = 'C:\Users\Tom\Documents\file.txt'

# 不推荐:基本字符串,需要双写反斜杠
path = "C:\\Users\\Tom\\Documents\\file.txt"

2. 数字:整数、浮点数、特殊值

integer = 42     # 整数
negative = -17    # 负数
float = 3.14159    # 浮点数
scientific = 1e6   # 科学计数法 = 1000000.0
hex = 0xDEADBEEF   # 十六进制
octal = 0o755     # 八进制
binary = 0b11010110  # 二进制

支持下划线增强可读性big_number = 1_000_000(等价于 1000000)

特殊浮点值(均为小写)

含义
inf / +inf / -inf 正无穷 / 负无穷
nan / +nan / -nan 非数字(Not a Number)

3. 布尔值:只有两个值,必须小写

is_enabled = true
debug_mode = false

注意:只能写 truefalse,不能写 TrueFALSE10。TOML 对此非常严格。

4. 日期时间:原生支持,无需自己解析

类型 格式 示例
偏移日期时间(带时区) RFC 33391979-05-27T07:32:00Z
本地日期时间 无时区1979-05-27T07:32:00
本地日期 YYYY-MM-DD1979-05-27
本地时间 HH:MM:SS07:32:00

5. 数组:方括号包裹,支持混合类型

colors = ["red", "yellow", "green"]
numbers = [1, 2, 3, 4]
mixed = [1, "two", true]    # 混合类型数组
nested = [[1, 2], [3, 4, 5]]  # 嵌套数组

数组可以跨多行书写,最后一个元素后的逗号可省略

fruits = [
  "apple",
  "banana",
  "cherry" # 逗号可选
]

什么是 TOML?零基础也能看懂的配置文件格式入门指南

五、TOML 的核心数据结构:表与数组表

如果说键值对是 TOML 的"原子",那么"表(Table)"就是 TOML 的"分子"。

1. 表(Table):用方括号定义,相当于"命名空间"

[database]
host = "localhost"
port = 5432
enabled = true

这等价于 JSON 中的:{"database": {"host": "localhost", "port": 5432, "enabled": true}}

2. 嵌套表:两种写法

# 方式1:点分隔(推荐)
[server.alpha]
ip = "10.0.0.1"
role = "frontend"

# 方式2:逐层定义
[server]
[server.beta]
ip = "10.0.0.2"
role = "backend"

3. 内联表:一行写完,适合简单结构

# 等价于上面的 [server.alpha] 定义
server = { ip = "10.0.0.1", role = "frontend" }

4. 数组表(Array of Tables):TOML 的杀手级特性 ⭐

当你需要配置多个同结构的对象时(比如多台服务器、多个用户),数组表是最佳选择。

[[servers]]
name = "Server1"
ip = "192.168.1.1"
port = 8080

[[servers]]
name = "Server2"
ip = "192.168.1.2"
port = 8081

这等价于 JSON 中的:

{"servers": [{"name": "Server1", "ip": "192.168.1.1", "port": 8080}, {"name": "Server2", "ip": "192.168.1.2", "port": 8081}]}

数组表是 TOML 相比 JSON 和 YAML 最大的优势之一——它能清晰表达"一组同类型配置项",且每个项可以有不同的键。

六、注释规则

TOML 只支持一种注释方式:# 从 # 开始到行尾的所有内容都是注释。

# 这是一个完整行的注释
name = "MyApp" # 这是行尾注释

注意:注释不能出现在字符串内部。

# 错误示例:
bad = "这不是#注释,这是字符串内容" # 整个值是字符串,# 不是注释

七、完整示例:一个真实的 TOML 配置文件

# 项目元数据
title = "My Awesome App"
version = "1.0.0"

[database]
enabled = true
host = "localhost"
port = 5432
username = "app_user"
password = "secret"

# 内联表
connection_pool = { max_connections = 20, timeout_seconds = 30 }

# 数组
supported_types = ["postgresql", "mysql"]

[servers.alpha]
ip = "10.0.0.1"
role = "frontend"

[servers.beta]
ip = "10.0.0.2"
role = "backend"

# 数组表
[[users]]
id = 1
name = "Alice"
hobbies = ["reading", "hiking"]

[[users]]
id = 2
name = "Bob"
hobbies = ["gaming"]

[cache]
redis_url = "redis://localhost:6379"
ttl_minutes = 60

八、Python 中如何读写 TOML

Python 3.11+:使用内置 tomllib(推荐)

Python 3.11 开始,标准库内置了 tomllib 模块,无需安装任何第三方库即可读取 TOML。

import tomllib

# 读取 TOML 文件(必须用 rb 模式打开)
with open("config.toml", "rb") as f:
  config = tomllib.load(f)

print(config["database"]["host"]) # 输出: localhost
print(config["servers"][0]["ip"])  # 输出: 10.0.0.1

从字符串解析

import tomllib

toml_str = """
title = "从字符串加载"
count = 5
is_active = true
"""
data = tomllib.loads(toml_str)
print(data) # {'title': '从字符串加载', 'count': 5, 'is_active': True}

数据类型自动转换对照表

TOML 类型 Python 类型 示例
stringstr"Hello""Hello"
integerint4242
floatfloat3.143.14
booleanbooltrueTrue
date-timedatetime.datetime2024-01-01T12:00:00Zdatetime 对象
arraylist[1, 2, 3][1, 2, 3]
tabledict[section]\nkey = "val"{"section": {"key": "val"}}
array of tableslist[dict][[sec]]\nkey = val[{"sec": {"key": "val"}}]

写入 TOML:Python 3.11+ 用 tomli-w

import tomli_w

config = {
  "project": {"name": "new_app", "version": "2.0.0"},
  "servers": [{"name": "server3", "ip": "192.168.1.3"}]
}

with open("new_config.toml", "w", encoding="utf-8") as f:
  tomli_w.dump(config, f, indent=2) # indent 控制缩进

Python 3.10 及以下:使用第三方库 tomli + tomli-w

pip install tomli tomli-w
import tomli # 读取
import tomli_w # 写入

旧方案:使用 toml 库(第三方,功能完整但非标准库)

pip install toml
import toml

# 读取
config = toml.load("config.toml")

# 写入
toml.dump(config, open("output.toml", "w"))

# 字符串转换
toml_str = toml.dumps(config)
print(toml_str)

九、TOML 最佳实践

  1. 键名使用小写字母,单词间用下划线或短横线分隔server_portserver-port,不要用 serverPort

  2. 表格命名使用有意义的名称,避免过深嵌套[database.connection.pool] 可以,但 [a.b.c.d.e] 不推荐

  3. 数组表保持一致的键结构:每个 [[users]] 块最好有相同的字段

  4. 路径使用字面量字符串(单引号):避免转义地狱

  5. 文件编码必须是 UTF-8:这是 TOML 规范的硬性要求

  6. TOML 没有 null 类型:如需表示空值,用空字符串 "" 或直接省略该键

十、常见陷阱与注意事项

陷阱 说明 正确做法
布尔值大小写TrueFALSE 都是错误的 只能用 true / false(全小写)
键名大小写敏感Namename 是不同的键 统一使用小写命名
不能重复定义同一键 后定义的会覆盖先定义的 避免重复,或使用数组表
注释不能在字符串内"# 不是注释" 整个是字符串 注释只能在键值对之外
浮点数 vs 整数42 是整数,42.0 是浮点数 TOML 严格区分,不会自动转换
日期时间精度 毫秒级是必须的,更高精度会被舍弃 按 RFC 3339 格式书写

十一、TOML 在真实项目中的应用

项目/工具 TOML 文件 用途
Python (Poetry)pyproject.toml 项目元数据、依赖管理、构建配置
Rust (Cargo)Cargo.toml 包信息、依赖声明、功能开关
Hugoconfig.toml 静态网站全局配置
GitHub Actions.github/workflows/*.yml(部分支持TOML) CI/CD 工作流
Denodeno.json(TOML 格式) 项目配置

一个典型的 pyproject.toml 示例

[build-system]
requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "my-package"
version = "1.0.0"
authors = [{name = "John Doe", email = "john@example.com"}]
dependencies = ["requests>=2.25.0"]

[project.optional-dependencies]
dev = ["pytest>=6.0", "black>=21.0"]

十二、相关工具推荐

总结

TOML 的本质,是用最少的语法符号,表达最丰富的配置信息。 它不追求花哨,只追求一件事:让人一眼就能看懂,让机器一解析就不会出错。

key = value 的简单键值对,到 [[table]] 的数组表;从 'C:\path' 的字面量字符串,到 2024-01-01T12:00:00Z 的原生日期时间——TOML 把配置文件该有的能力,全部给齐了,而且给得优雅。

如果你正在为项目选配置文件格式,TOML 是一个不会后悔的选择。

相关工具

TOML转JSON工具

TOML转JSON工具

工具类型: 开发工具
使用次数: 29
JSON转TOML工具

JSON转TOML工具

工具类型: 开发工具
使用次数: 21
打赏
THE END
作者头像
fuwa
我爱我的参差不齐 我即是自己的反义词