从零开始学习 TOML,配置文件的新选择

TOML(Tom's Obvious, Minimal Language)类似于 JSON 或 YAML,常用于存储配置数据,但语法更简洁,旨在替代语法冗余的 JSON 或功能有限的 INI,成为最小化、易读、无歧义的配置文件格式。

TOML 被广泛应用于各种工具和语言的配置文件中,例如:

  • Rust 的包管理器 Cargo 使用 Cargo.toml
  • Python 的项目管理工具 Poetry 使用 pyproject.toml
  • Hugo 静态站点生成器使用 config.toml
  • GitHub Actions 的工作流文件也支持使用 TOML 格式。

本教程将详细介绍 TOML 的核心语法、数据类型、高级特性,并通过实例帮助你快速上手。

一、基本语法规则

TOML 的语法设计遵循 "直观、一致、无歧义" 的原则,所有规则都围绕 "让人类易读、机器易解析" 展开,在编写 TOML 文件时,需要遵守以下基本的语法规范。

1. 文件扩展名

TOML 文件使用 .toml 作为扩展名,例如项目配置文件 config.toml、依赖管理文件 pyproject.toml

2. 注释规则

注释用于添加说明信息,解析器会忽略注释内容,语法为:

  • # 开头,从 # 到行尾的所有字符均为注释;
  • 支持两种注释形式:行注释(# 开头占一行)和行尾注释(# 跟在键值对后);
  • 注意:字符串内部的 # 不视为注释标识,会被当作普通字符解析。

示例:

toml 复制代码
# 这是一个完整的行注释
name = "TOML" # 这是一个行尾注释
another = "# 这不是一个注释"

3. 键值对

键值对是 TOML 文件的基本元素,。每个键值对由一个键和一个值组成,用 = 分隔:

toml 复制代码
key = "value"

一个完整的键值对(键 + = + 值)必须写在同一行,不能跨越多行拆分。

3.1 键

键(Key)是键值对的标识,用于唯一标识一个值,TOML 提供了多种键的定义方式:

  • 裸键(Bare Key) :直接书写,不使用引号包裹,仅允许包含 ASCII 字母(A-Z、a-z)、ASCII 数字(0-9)、下划线(_)和短横线(-

    toml 复制代码
    123key = "value"
    server_port = 80
  • 引号键(Quoted Key) :当键名中使用空格、特殊字符(如 @, #, $)或非 ASCII 字符(如中文)时,必须用双引号(")或单引号(')包裹。

    toml 复制代码
    "server address" = "192.168.1.1"
    'app-version' = "1.0.0"
    "中文键名" = "测试内容"
3.2 值

值是配置项的具体内容。TOML 支持多种数据类型,以满足不同的配置需求。

4. 赋值

键值对的键和值之间必须使用 = 分隔:

toml 复制代码
key = "value"

键在 = 左侧,值在 = 右侧。

5. 大小写敏感

键名、类型标识(如 true/false)均区分大小写,例如 Namename 是两个独立的键,True 不能替代 true

toml 复制代码
name
Name

二、基本数据类型

TOML 支持多种数据类型,下面逐一介绍:TOML 的数据类型分为「基础类型」和「复合类型」,覆盖配置场景的所有需求:

1. 字符串 (String)

字符串是最常用的数据类型,TOML 提供了多种写法以适应不同场景。

  • 基本字符串 (Basic String) :用双引号 " 包裹。支持转义字符,如 \n (换行)、\t (制表符)、\" (双引号)、\\ (反斜杠) 等。

    toml 复制代码
    title = "My \"Awesome\" Project"
    description = "Line 1\nLine 2" # 会解析为换行
  • 多行基本字符串 (Multi-line Basic String) :用三个双引号 """ 包裹。可以跨越多行,其中的换行符会被保留。同样支持转义字符。

    toml 复制代码
    long_text = """
    This is a multi-line string.
    Line 2.
    "Quotes" are allowed without escaping (except for triple quotes).
    """
  • 字面量字符串 (Literal String) :用单引号 ' 包裹。不支持任何转义字符 ,所见即所得。不解析任何转义字符(适合写路径、正则表达式等)

    toml 复制代码
    path = 'C:\Users\Name\Documents\file.txt' # 这里的 \ 就是普通字符
    regex = '^\d{3}-\d{2}-\d{4}$'           # 正则表达式中的 \d 不会被转义
  • 多行字面量字符串 (Multi-line Literal String) :用三个单引号 ''' 包裹。同样不支持转义,可以跨越多行,换行符会被保留。

    toml 复制代码
    code_block = '''
    def hello():
        print('Hello, World!')
    '''

2. 整数 (Integer)

表示整数,支持十进制、十六进制、八进制和二进制。支持整数、浮点数、正负号,以及十六进制 / 八进制 / 二进制(用前缀标识):

toml 复制代码
# 整数
age = 25
count = -10

# 浮点数
pi = 3.14159
price = 19.99
negative_float = -0.5

# 其他进制(前缀区分)
hex = 0xDEADBEEF  # 十六进制(0x 开头)
octal = 0o755     # 八进制(0o 开头)
binary = 0b1010   # 二进制(0b 开头)

3. 浮点数 (Float)

表示小数,也支持科学记数法。

toml 复制代码
pi = 3.14159
price = 19.99
negative_float = -0.5
scientific_notation = 1e6      # 等于 1000000.0
another_sci_notation = 2.5e-3  # 等于 0.0025

也可以表达特殊的浮点数值。它们总是小写的:

toml 复制代码
# infinity
sf1 = inf  # positive infinity
sf2 = +inf # positive infinity
sf3 = -inf # negative infinity

# not a number
sf4 = nan  # actual sNaN/qNaN encoding is implementation-specific
sf5 = +nan # same as `nan`
sf6 = -nan # valid, actual encoding is implementation-specific

4. 布尔值 (Boolean)

只有 truefalse必须小写 ,不能写 True/FALSE):

toml 复制代码
enabled = true
debug_mode = false

5. 日期时间 (Date and Time)

TOML 内置了对日期、时间和日期时间的支持,精确到秒或毫秒,格式基于 ISO 8601 标准:

  • 本地日期YYYY-MM-DD

    toml 复制代码
    release_date = 2025-11-19
  • 本地时间HH:MM:SSHH:MM:SS.sss (带毫秒)

    toml 复制代码
    start_time = 09:30:00
    precise_time = 14:45:30.123
  • 本地日期时间YYYY-MM-DDTHH:MM:SSYYYY-MM-DDTHH:MM:SS.sss (日期和时间之间用 T 分隔)

    toml 复制代码
    event_datetime = 2023-10-27T15:00:00
  • 带时区的日期时间YYYY-MM-DDTHH:MM:SSZ(Z 表示 UTC 时区)或 YYYY-MM-DDTHH:MM:SS±HH:MM(时区偏移)

    toml 复制代码
    deadline_utc = 2023-10-28T00:00:00Z
    meeting_time = 2023-10-27T10:00:00+08:00 # 东八区

三、复合数据类型

为了表示更复杂的结构,TOML 提供了数组 (Array)表 (Table)

1. 数组 (Array)

数组用方括号 [] 包裹,元素之间用逗号 , 分隔,支持不同类型的元素(但推荐同类型,更规范):

toml 复制代码
# 整数数组
numbers = [1, 2, 3, 4]

# 混合类型数组
mixed = [1, "hello", true, 3.14]

# 嵌套数组
matrix = [
  [1, 2],
  [3, 4]
]

2. 表格 (Table)

表格(Table)用于表示结构化的数据集合,对应 JSON 的「Object」。在头部使用方括号 [table_name] 定义:

toml 复制代码
[table]

[table_name] 直到下一个表格定义或 EOF 之间都是该表的键值。 表中的键/值对并不保证会按特定顺序排列:

toml 复制代码
# 定义一个名为 'database' 的表
[database]
server = "192.168.1.1"
ports = [8001, 8001, 8002]
connection_max = 5000
enabled = true

上面的 TOML 片段大致等同于以下 JSON:

json 复制代码
{
  "database": {
    "server": "192.168.1.1",
    "ports": [8001, 8001, 8002],
    "connection_max": 5000,
    "enabled": true
  }
}
嵌套表格 (Nested Tables)

你也可以通过点 . 分隔层级来表示嵌套的结构

toml 复制代码
# 嵌套表格(用 . 分隔层级)
[server.ports]
http = 80
https = 443

这等同于:

json 复制代码
{
  "server": {
    "ports": {
      "http": 80,
      "https": 443
    }
  }
}

你也可以分层次定义,但直接定义更简洁:

toml 复制代码
[server]
hostname = "example.com"

[server.ports] # 这会在已有的 'server' 表下创建 'ports' 子表
http = 80
https = 443
内联表格 (Inline Table)

对于结构简单的表,可以使用内联表语法,用大括号 {} 包裹,写在一行内:

toml 复制代码
author = { name = "John Doe", email = "john@example.com" }

这等同于:

toml 复制代码
[author]
name = "John Doe"
email = "john@example.com"

内联表也可以嵌套:

toml 复制代码
server = { address = "10.0.0.1", ports = { http = 8080, https = 8443 } }

3. 数组表格(Array of Tables)

当你需要一个表的数组(即 JSON 中的数组对象)时,可以使用双括号 [[]]标注的标题来表示:

toml 复制代码
[[table_array]]

每个 [[table_array]] 表示数组中的一个元素(对象),对应 JSON 的「对象数组」:

toml 复制代码
# 定义一个名为 'products' 的数组表
[[products]]
name = "Hammer"
sku = 738594937

[[products]] # empty table within the array

[[products]]
name = "Screwdriver"
price = 9.99 # 数组表中的每个元素可以有不同的键

头部的第一个实例定义了数组及其第一个表元素,并且每个后续实例都会在该数组中创建并定义一个新的表元素,这些表按遇到的顺序插入数组。上面的 TOML 片段大致等同于以下 JSON:

json 复制代码
{
  "products": [
    { "name": "Hammer", "sku": 738594937 },
    { },
    { "name": "Screwdriver", "price": 9.99 }
  ]
}

数组表也可以嵌套:

toml 复制代码
[[fruit]]
  name = "apple"

  [[fruit.varieties]]
    name = "red delicious"

  [[fruit.varieties]]
    name = "granny smith"

[[fruit]]
  name = "banana"

  [[fruit.varieties]]
    name = "cavendish"

这会被解析为一个包含两个 fruit 对象的数组,每个 fruit 对象内部又有一个 varieties 数组,对应 JSON 如下:

json 复制代码
{
  "fruit": [
    {
      "name": "apple",
      "varieties": [
        {
          "name": "red delicious"
        },
        {
          "name": "granny smith"
        }
      ]
    },
    {
      "name": "banana",
      "varieties": [
        {
          "name": "cavendish"
        }
      ]
    }
  ]
}

四、实践中的 TOML 示例

下面是一个综合性的 pyproject.toml 示例,它展示了 TOML 的多种特性:

toml 复制代码
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

[tool.poetry]
name = "my-python-project"
version = "0.1.0"
description = "A sample Python project managed with Poetry."
authors = [
    "Your Name <your.email@example.com>"
]
license = "MIT"
readme = "README.md"
keywords = ["sample", "demo", "poetry"]

[tool.poetry.dependencies]
python = "^3.9"
requests = "^2.26.0"
numpy = "^1.21.0"

[tool.poetry.dev-dependencies]
pytest = "^6.2.5"
black = "^21.9b0"
isort = "^5.9.3"

[tool.black]
line-length = 88
target-version = ['py39']

[tool.isort]
profile = "black"
multi
相关推荐
vvoennvv3 小时前
【Python TensorFlow】 TCN-LSTM时间序列卷积长短期记忆神经网络时序预测算法(附代码)
python·神经网络·机器学习·tensorflow·lstm·tcn
nix.gnehc3 小时前
PyTorch
人工智能·pytorch·python
z***3353 小时前
SQL Server2022版+SSMS安装教程(保姆级)
后端·python·flask
二川bro4 小时前
Scikit-learn全流程指南:Python机器学习项目实战
python·机器学习·scikit-learn
代码的乐趣4 小时前
支持selenium的chrome driver更新到142.0.7444.175
chrome·python·selenium
数据知道4 小时前
Django基础项目:从零到一搭建用户管理系统
python·django·python web·python项目
z樾5 小时前
TorchRL-MADDPG
pytorch·python·深度学习
Yue丶越5 小时前
【Python】基础语法入门(三)
开发语言·python