版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第Python解析toml配置文件的方法分享目录楔子举个例子注释键值对字符串整数浮点数布尔值日期数组表行内表表数组
楔子
上一篇文章我们介绍了yaml,虽然yaml的表达能力已经很丰富了,但GitHub觉得还是不够优雅,所以鼓捣出了一个toml。toml有着比yaml更简洁的语法,它的目标就是成为一个最简单的配置文件格式。
然后Python解析toml文件需要使用一个名字也叫toml的库,直接pipinstalltoml即可。
举个例子
有了ini和yaml,相信toml学习来也很简单,先直接看一个例子吧。
import
toml
config
=
"""
title
=
"toml
小栗子"
[owner]
name
=
"古明地觉"
age
=
17
place
=
"东方地灵殿"
nickname
=
["小五",
"少女觉",
"觉大人"]
[database]
host
=
""
port
=
5432
username
=
"satori"
password
=
"123456"
echo
=
true
[server]
[server.v1]
api
=
"1.1"
enable
=
false
[server.v2]
api
=
"1.2"
enable
=
true
[client]
client
=
[
["socket",
"webservice"],
[5555]
address
=
[
"xxxx",
"yyyy"
#loads:从字符串加载
#load:从文件加载
#dumps:生成toml格式字符串
#dump:生成toml格式字符串并写入文件中
data
=
toml.loads(config)
print(data)
'title':
'toml
小栗子',
'owner':
{'name':
'古明地觉',
'age':
17,
'place':
'东方地灵殿',
'nickname':
['小五',
'少女觉',
'觉大人']},
'database':
{'host':
'',
'port':
5432,
'username':
'satori',
'password':
'123456',
'echo':
True},
'server':
{'v1':
{'api':
'1.1',
'enable':
False},
'v2':
{'api':
'1.2',
'enable':
True}},
'client':
{'client':
[['socket',
'webservice'],
[5555]],
'address':
['xxxx',
'yyyy']}
"""
toml是采用var=value的形式进行配置,然后也有类似于ini里面的section,每个section都是字典中的一个key,然后该key也对应一个字典。但是我们注意看最开始的title,由于它上面没有section,所以它是一个单独的key。
而且还有一点就是toml支持嵌套,我们看到server.v1,表示v1是server对应的字典里面的一个key,然后v1对应的值还是一个字典。
toml变得更加简单了,而且写来也非常像Python,它有如下特点:
toml文件是大小写敏感的;
toml文件必须是有效的UTF-8编码的Unicode文档;
toml文件的空白符应该是Tab或者空格;
toml文件的换行是LF或者CRLF;
然后我们来介绍一下toml的数据结构。
注释
toml采用#表示注释,举个例子:
#
这是注释
key
=
"value"
#
也是注释
可以解析一下看看会得到什么,剧透:会得到只包含一个键值对的字典。
键值对
TOML文档最基本的构成区块是键值对,键名在等号的左边、值在右边,并且键名和键值周围的空白会被忽略。此外键、等号和值必须在同一行(不过有些值可以跨多行)。
key
=
"value"
键名可以是裸露的(裸键),引号引起来的(引号键),或点分隔的(点分隔键)。裸键只能包含:ascii字符、ascii数字、下划线、短横线。
import
toml
config
=
"""
key
=
"value"
bare_key
=
"value"
bare-key
=
"value"
#
1234
会被当成字符串
1234
=
"value"
data
=
toml.loads(config)
print(data)
{'key':
'value',
'bare_key':
'value',
'bare-key':
'value',
'1234':
'value'}
"""
如果不是裸键,那么就必须使用引号括起来,但是此时也支持我们使用更加广泛的键名,但除了特殊场景,否则使用裸键是最佳实践。
import
toml
config
=
"""
""
=
"value"
"character
encoding"
=
"value"
"ʎǝʞ"
=
"value"
'key2'
=
"value"
'quoted
"value"'
=
"value"
data
=
toml.loads(config)
print(data)
{'':
'value',
'character
encoding':
'value',
'ʎǝʞ':
'value',
'key2':
'value',
'quoted
"value"':
'value'}
"""
注意:裸键不能为空,但空引号键是允许的(虽然不建议如此)。
=
"没有键名"
#
错误
""
=
"空"
#
正确但不鼓励
''
=
'空'
#
正确但不鼓励
然后是点分隔键,它是一系列通过点相连的裸键或引号键,这允许我们将相近属性放在一起:
import
toml
config
=
"""
name
=
"橙子"
physical.color
=
"橙色"
physical.shape
=
"圆形"
site.""
=
true
=
true
a.b.c.d
=
123
data
=
toml.loads(config)
print(data)
'name':
'橙子',
'physical':
{'color':
'橙色',
'shape':
'圆形'},
'site':
{'':
True,
'google':
{'com':
True}},
'a':
{'b':
{'c':
{'d':
123}}}
"""
我们看到这个点分隔符不错哟,自动实现了嵌套结构,并且点分隔符周围的空白会被忽略。
=
"香蕉"
#
这是最佳实践
fruit.
color
=
"黄色"
#
等同于
fruit.color
fruit
.
flavor
=
"香蕉"
#
等同于
fruit.flavor
注意:多次定义同一个键是不行的。
import
toml
config
=
"""
#
name
和
"name"
是等价的
name
=
"古明地觉"
"name"
=
"古明地恋"
data
=
toml.loads(config)
except
toml.decoder.TomlDecodeError
as
e:
print(e)
Duplicate
keys!
(line
4
column
1
char
36)
"""
对于点分隔键也是如此,只要一个键还没有被直接定义过,我们就仍可以对它和它下属的键名赋值。
import
toml
config
=
"""
fruit.apple.smooth
=
true#
此时可以继续操作
fruit、fruit.apple,它们都是字典
#
给
fruit
这个字典加一个
key
fruit.orange
=
2
#
给
fruit.apple
加一个
key
fruit.apple.color
=
"red"
data
=
toml.loads(config)
print(data)
'fruit':
{'apple':
{'smooth':
True,
'color':
'red'},
'orange':
2}
"""
但下面这个操作是不行的:
#
将
fruit.apple
的值定义为一个整数
fruit.apple
=
1
#
但接下来就不合法了,因为整数不能变成字典
fruit.apple.smooth
=
true
#
如果我们设置
fruit.apple
=
{},那么第二个赋值是可以的
#
没错,我们可以通过
{}
直接创建一个字典
可以看到,真的很像Python。然后再来说一个特例:
import
toml
config
=
"""
3.14
=
"pi"
"3.14"
=
"pi"
data
=
toml.loads(config)
print(data)
{'3':
{'14':
'pi'},
'3.14':
'pi'}
"""
如果键是浮点数,那么需要使用引号括起来,否则会被解释为点分隔键。
看完了键,再来看看值(value),其实对于toml来说,值比键要简单的多得多。
字符串
字符串共有四种方式来表示:基础式的,多行基础式的,字面量式的,和多行字面量式的。
1)基础字符串由引号包裹,任何Unicode字符都可以使用,除了那些必须转义的。
import
toml
config
=
"""
str
=
'我是一个字符串,"你可以把我引起来"'
data
=
toml.loads(config)
print(data)
{'str':
'我是一个字符串,"你可以把我引起来"'}
"""
2)多行字符串由三个引号包裹,允许换行,注意:紧随开头引号的换行会被去除,其它空白和换行会被原样保留。
import
toml
config
=
"""
str
=
'''
玫瑰是红色的
紫罗兰是蓝色的
data
=
toml.loads(config)
print(data)
{'str':
'玫瑰是红色的\n紫罗兰是蓝色的\n'}
"""
这里的引号可以是双引号、也可以是单引号。
整数
整数是纯数字,正数可以有加号前缀,负数的前缀是减号。
import
toml
config
=
"""
int1
=
+99
int2
=
42
int3
=
0
int4
=
-17
#
对于大数,可以在数字之间用下划线来增强可读性
#
每个下划线两侧必须至少有一个数字。
int5
=
1_000
int6
=
5_349_221
int7
=
53_49_221
#
印度记数体系分组
int8
=
1_2_3_4_5
#
无误但不鼓励
data
=
toml.loads(config)
print(data)
{'int1':
99,
'int2':
42,
'int3':
0,
'int4':
-17,
'int5':
1000,
'int6':
5349221,
'int7':
5349221,
'int8':
12345}
"""
但是注意:数字不能以零开头,除了0本身。当然-0与+0也是有效的,并等同于无前缀的零。非负整数值也可以用十六进制、八进制或二进制来表示。
#
带有
`0x`
前缀的十六进制,大小写均可
hex1
=
0xDEADBEEF
hex2
=
0xdeadbeef
hex3
=
0xdead_beef
#
带有
`0o`
前缀的八进制
oct1
=
0o01234567
oct2
=
0o755
#
对于表示
Unix
文件权限很有用
#
带有
`0b`
前缀的二进制
bin1
=
0b11010110
浮点数
一个浮点数由一个整数部分(遵从与十进制整数值相同的规则)后跟上一个小数部分、或一个指数部分组成。如果小数部分和指数部分兼有,那小数部分必须在指数部分前面。
import
toml
config
=
"""
flt1
=
+1.0
flt2
=
3.1415
flt3
=
-0.01
flt4
=
5e+22
flt5
=
1e06
flt6
=
-2E-2
flt7
=
6.626e-34
data
=
toml.loads(config)
print(data)
{'flt1':
1.0,
'flt2':
3.1415,
'flt3':
-0.01,
'flt4':
5e+22,
'flt5':
1000000.0,
'flt6':
-0.02,
'flt7':
6.626e-34}
"""
小数部分是一个小数点后跟一个或多个数字,一个指数部分是一个E(大小写均可)后跟一个整数部分(遵从与十进制整数值相同的规则,但可以包含前导零)。小数点,如果有用到的话,每侧必须紧邻至少一个数字。
#
非法的浮点数
invalid_float_1
=
.7
invalid_float_2
=
7.
invalid_float_3
=
3.e+20
与整数相似,可以使用下划线来增强可读性,每个下划线必须被至少一个数字围绕。
flt8
=
224_617.445_991_228
浮点数值-0.0与+0.0是有效的,并且应当遵从IEEE754。特殊浮点值也能够表示:
#
无穷
sf1
=
inf
#
正无穷
sf2
=
+inf
#
正无穷
sf3
=
-inf
#
负无穷
sf4
=
nan
#
是对应信号非数码还是静默非数码,取决于实现
sf5
=
+nan
#
等同于
`nan`
sf6
=
-nan
#
正确,实际码取决于实现
布尔值
布尔值就是惯用的那样,但要小写。
bool1
=
true
bool2
=
false
日期
可以是普通的datetime,或者是遵循ISO-8859-1格式的日期。
import
toml
config
=
"""
dt1
=
2025-01-01T12:33:22+00:00
dt2
=
2025-11-12
12:11:33
dt3
=
2025-11-23
data
=
toml.loads(config)
print(data)
{'dt1':
datetime.datetime(2025,
1,
1,
12,
33,
22,
tzinfo=...),
'dt2':
datetime.datetime(2025,
11,
12,
12,
11,
33),
'dt3':
datetime.date(2025,
11,
23)}
"""
数组
语法和Python的列表类似:
import
toml
config
=
"""
#
每个数组里面的元素类型要一致
integers
=
[1,
2,
3]
colors
=
["红",
"黄",
"绿"]
nested_array_of_ints
=
[[1,
2],
[3,
4,
5]]
nested_mixed_array
=
[[1,
2],
["a",
"b",
"c"]]
numbers
=
[0.1,
0.2,
0.5]
data
=
toml.loads(config)
print(data)
{'colors':
['红',
'黄',
'绿'],
'integers':
[1,
2,
3],
'nested_array_of_ints':
[[1,
2],
[3,
4,
5]],
'nested_mixed_array':
[[1,
2],
['a',
'b',
'c']],
'numbers':
[0.1,
0.2,
0.5]}
"""
数组可以跨行,数组的最后一个值后面可以有终逗号(也称为尾逗号)。
import
toml
config
=
"""
integers2
=
[
1,
2,
3
integers3
=
[
2,
#
这是可以的
data
=
toml.loads(config)
print(data)
{'integers2':
[1,
2,
3],
'integers3':
[1,
2]}
"""
表
表,完全可以把它想象成ini的section。
import
toml
config
=
"""
#
表名的定义规则与键名相同
#
解析之后得到的大字典中就有
"table-1"
这个
key
#
并且其
value
也是一个表,在它下方
#
直至下一个表头或文件结束,都是这个表内部的键值对
[table-1]
key1
=
"some
string"
key2
=
123
[table-2]
key1
=
"another
string"
key2
=
456
data
=
toml.loads(config)
print(data)
{'table-1':
{'key1':
'some
string',
'key2':
123},
'table-2':
{'key1':
'another
string',
'key2':
456}}
"""
但是我们之前也实现过类似于这种结构,没错,就是点分隔符:
import
toml
config
=
"""
#
所以
other-table-1
和
table-1
是等价的
#
other-table-2
和
table-2
是等价的
other-table-1.key1
=
"some
string"
other-table-1.key2
=
123
other-table-2.key1
=
"another
string"
other-table-2.key2
=
456
[table-1]
key1
=
"some
string"
key2
=
123
[table-2]
key1
=
"another
string"
key2
=
456
data
=
toml.loads(config)
print(data)
{'other-table-1':
{'key1':
'some
string',
'key2':
123},
'other-table-2':
{'key1':
'another
string',
'key2':
456},
'table-1':
{'key1':
'some
string',
'key2':
123},
'table-2':
{'key1':
'another
string',
'key2':
456}}
"""
不过注意:我们必须要把other-table-1和other-table-2定义在上面,如果我们定义在下面看看会有什么后果:
import
toml
config
=
"""
[table-1]
key1
=
"some
string"
key2
=
123
[table-2]
key1
=
"another
string"
key2
=
456
other-table-1.key1
=
"some
string"
other-table-1.key2
=
123
other-table-2.key1
=
"another
string"
other-table-2.key2
=
456
data
=
toml.loads(config)
print(data)
'table-1':
{'key1':
'some
string',
'key2':
123},
'table-2':
{'key1':
'another
string',
'key2':
456,
'other-table-1':
{'key1':
'some
string',
'key2':
123},
'other-table-2':
{'key1':
'another
string',
'key2':
456}}
"""
估计你已经猜到了,它们被当成了table-2对应的字典里面的key了。此外我们还可以将上面两种方式结合起来:
import
toml
config
=
"""
#
[]
里面的不再是一个普通的键,而是点分隔键
#
另外键名周围的空格会被忽略,但是最好不要有
[dog
.
"tater.man"]
=
"哈巴狗"
data
=
toml.loads(config)
print(data)
'dog':
{'tater.man':
{'type':
{'name':
'哈巴狗'}}}
"""
表的里面也是可以没有键值对的:
import
toml
config
=
"""
[x.y.z.w.a.n]
[x.m]
[x.n]
a.b.c
=
"xxx"
data
=
toml.loads(config)
print(data)
{'x':
{
'a':
{'b':
{'c':
'xxx'}},
'm':
{},
'n':
{},
'y':
{'z':
{'w':
{'a':
{'n':
{}}}}}
}
"""
总的来说还是蛮强大的,但是要注意:不能重复定义。
行内表
行内表提供了一种更为紧凑的语法来表示表,因为上面每一个键值对都需要单独写一行,比如:
[table1]
a
=
1
b
=
2
c
=
3
#
最终可以得到
#
{'table1':
{'a':
1,
'b':
2,
'c':
3}}
但是除了上面的表达方式之外,我们还可以采用行内表:
import
toml
config
=
"""
#
和
Python
字典的表示方式略有不同
#
并且也支持多种
key
table1
=
{a
=
1,
b
=
"二",
c.a
=
"3"}
table2
=
{c."b
c".d
=
"4"}
data
=
toml.loads(config)
print(data)
'table1':
{'a':
1,
'b':
'二',
'c':
{'a':
'3'}},
'table2':
{'c':
{'b
c':
{'d':
'4'}}}
"""
表数组
然后来看看数组和表的结合:
import
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 市政冰雪应急预案(3篇)
- 健康周活动策划方案(3篇)
- 吧台弧形施工方案(3篇)
- 庄园烧烤营销方案(3篇)
- 光明牛奶营销方案(3篇)
- 19套施工方案(3篇)
- 传统拜神活动策划方案(3篇)
- 批发纱窗营销方案(3篇)
- 整体起吊施工方案(3篇)
- 春节广电营销方案(3篇)
- 医院排队叫号系统方案
- 文印服务投标方案(技术方案)
- 迪尔S系列联合收割机
- 仓管工作日志范文(精选4篇)
- Unit5+Developing+ideas+coast+to+coast+课件【知识 精讲精研 】 高中英语外研版(2019)必修第二册
- 初中物理竞赛辅导―机械运动
- GB/T 4897-2015刨花板
- GB/T 32260.2-2015金属材料焊缝的破坏性试验焊件的冷裂纹试验弧焊方法第2部分:自拘束试验
- 人体发育-胎儿期发育课件
- 中国石油天然气集团公司-石油企业职工个人劳动防护用品管理及配备规定
- JB∕T 7301-2017 手持式凿岩机
评论
0/150
提交评论