什么是TOML——配置Python应用程序的一种更简单的方法

1,947 阅读5分钟

TOML使编写配置文件变得简单、直接,而且比许多其他格式(包括JSON)更易于人类阅读。

有趣的是,一些最简单的软件开发决定也变成了最困难的决定。一个例子是为你的应用程序或服务选择配置文件格式。当然,我们会想到JSON和YAML。但如果你需要一种易于理解相对容易解析为数据结构的配置文件格式,你可以考虑TOML。

TOML,即Tom's Obvious Minimal Language,主要是为存储配置数据而创建的,具有JSON和其他格式所缺乏的功能。举例来说,JSON不支持内联注释。TOML让你插入注释,只需在它们前面加上一个哈希符号,就像你在Python中那样。那么,Python本身正在向TOML靠拢,作为一种配置标准,这就不奇怪了。(参见pyproject.tomlpip 用来装包)。

TOML格式基础知识

TOML格式文件由键值对组成,其中键是字符串,值可以是多种类型中的一种。在某些方面,它让人想起了微软的Windows.ini 文件格式,但支持更多的数据类型。

这里有一个例子:

name = "string"
integer = 3
float-value = 3.14159
boolean_value = true
"quoted ünicode key" = true
# this is a comment
data = "OK" # a comment after a key/value

键总是被解释为字符串。可以是字符串、整数、浮点数、布尔值、各种类型的日期时间值,以及两种特殊的值,即数组内联表。(稍后会有更多关于这些的内容)。

哈希符号之后到行尾的所有内容都是注释。这不包括作为键或值字符串本身一部分的哈希符号。

TOML中的数组

数组是一种在单个键中存储多个值的方法:

int_values = [1, 2, 4, 8, 16]
strings = ["prime", "audio", "soup"]
mixed = [1, 2, "Three", 4.0]
multi-line = [
    "array",
    "of",
    "strings"
]

正如你所猜测的,数组不一定都要包含相同类型的值。而且如果需要的话,它们的定义可以跨越多行。在 Python 中,数组直接映射为列表。

TOML中的表

表是TOML 文件中键值对的集合,用方括号标明标题。 在 Python 中,表的处理就像一个嵌套的字典:

[general]
make_network_connection = true
ping_time = 1200

[user]
default_name = "Anonymous"
ping_time = 1600

微软的 Windows.ini 文件格式有一个类似的功能,并且有一个类似的功能。它允许键值对的分组有自己独立的命名空间。ping_time 例如,generaluser 的值在它们自己的命名空间中是不同的;一个不会覆盖另一个。

带点的名字、内联表和表数组

在TOML中产生与表格相同的命名间隔效果的另一种方法是使用带点的名字。下面是上述例子的呈现方式:

general.make_network_connection = true
general.ping_time = 1200

user.default_name = "Anonymous"
user.ping_time = 1600

然而,另一种方法是使用内联表,这是一种更紧凑的风格,对于某些值的集合来说可能更容易阅读:

general = {make_network_connection = true, ping_time = 1200}
user = {default_name = "Anonymous", ping_time = 1600}

请注意,内联表的格式从表面上看可能与 Python 字典声明相似,但它不是;它使用= 而不是: 来描述键/值对。

你还可以用表做一件事,那就是创建一个表的数组,或者说一个表数组

[[movies]]
name = "Blade Runner"
year = 1982
[[movies]]
name = "Blade Runner 2049"
year = 2017

这创建了一个嵌套结构,类似于下面的JSON:

movies = {
    {name: "Blade Runner", year: 1982},
    {name: "Blade Runner 2049", year: 2017}
}

在Python中使用TOML

因为Python生态系统的一些部分现在使用TOML作为配置语言,所以Python对TOML的支持正在增长。

从Python 3.11开始,一个用于TOML的标准库模块tomllib提供了一种Python原生的方法来读取TOML并将其解析为Python对象,主要是字典。然而,这就是 tomllib ,它没有将Python对象序列化为TOML文件,所以它不适合读写TOML;只适合阅读。

Python 核心团队可能最终会将编写 TOML 作为tomllib 的一部分,但预计不会很快发生。同时,tomllib 模块对于从配置文件中摄取和解析 TOML 非常有用,而不需要外部库。如果你需要将Python对象序列化为TOML,有几个第三方的解决方案:

  • tomli-w是一个最小的库,用于把Python字典写成TOML。请注意,它并不对所写的TOML进行自动验证;为此,你要用tomllib 加载数据,看看它是否有效。
  • tomlkit可以从 TOML 中读出写出,所以它是一个相当完整的解决方案,特别是如果你需要支持早于 3.11 的 Python 版本 (大多数人都会这样做)。

TOML的问题

最后,有几个需要注意的问题,特别是当你手工编写TOML时:

  1. 注意直接将键名映射到你使用的语言不支持的程序变量名。例如,Python 允许在变量名称中使用下划线,但不允许使用破折号,所以上面的键float-value 不能直接映射到具有这个名称的变量。然而,它可以被映射到一个字典中的一个键,因为Python字典的键可以是任何字符串。

  2. TOML中的布尔值使用JSON渲染。一个例子是使用JSON的truefalse ,而不是Python的特异功能TrueFalse 。TOML库应该自动处理这个问题,但是在手工编写TOML的时候要注意这个问题。