亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Python解析toml配置文件的方法分享

 更新時間:2022年09月18日 10:04:47   作者:古明地覺  
在開發(fā)過程中,配置文件是少不了的,而且配置文件是有專門的格式的,比如:ini,yaml,toml等等。本文帶大家來看看Python如何解析toml文件,需要的可以參考一下

楔子

上一篇文章我們介紹了 yaml,雖然 yaml 的表達(dá)能力已經(jīng)很豐富了,但 GitHub 覺得還是不夠優(yōu)雅,所以鼓搗出了一個 toml。toml 有著比 yaml 更簡潔的語法,它的目標(biāo)就是成為一個最簡單的配置文件格式。

然后 Python 解析 toml 文件需要使用一個名字也叫 toml 的庫,直接 pip install toml 即可。

舉個例子

有了 ini 和 yaml,相信 toml 學(xué)習(xí)來也很簡單,先直接看一個例子吧。

import?toml

config?=?"""
title?=?"toml?小栗子"

[owner]
name?=?"古明地覺"
age?=?17
place?=?"東方地靈殿"
nickname?=?["小五",?"少女覺",?"覺大人"]

[database]
host?=?"127.0.0.1"
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':?'127.0.0.1',?
?????????????????'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 的形式進(jìn)行配置,然后也有類似于 ini 里面的 section,每個 section 都是字典中的一個 key,然后該 key 也對應(yīng)一個字典。但是我們注意看最開始的 title,由于它上面沒有 section,所以它是一個單獨(dú)的 key。

而且還有一點(diǎn)就是 toml 支持嵌套,我們看到 server.v1,表示 v1 是 server 對應(yīng)的字典里面的一個 key,然后 v1 對應(yīng)的值還是一個字典。

toml 變得更加簡單了,而且寫來也非常像 Python,它有如下特點(diǎn):

toml 文件是大小寫敏感的;

toml 文件必須是有效的 UTF-8 編碼的 Unicode 文檔;

toml 文件的空白符應(yīng)該是 Tab 或者空格;

toml 文件的換行是 LF 或者 CRLF;

然后我們來介紹一下 toml 的數(shù)據(jù)結(jié)構(gòu)。

注釋

toml 采用 # 表示注釋,舉個例子:

#?這是注釋
key?=?"value"??#?也是注釋

可以解析一下看看會得到什么,劇透:會得到只包含一個鍵值對的字典。

鍵值對

TOML 文檔最基本的構(gòu)成區(qū)塊是鍵值對,鍵名在等號的左邊、值在右邊,并且鍵名和鍵值周圍的空白會被忽略。此外鍵、等號和值必須在同一行(不過有些值可以跨多行)。

key?=?"value"

鍵名可以是裸露的(裸鍵),引號引起來的(引號鍵),或點(diǎn)分隔的(點(diǎn)分隔鍵)。裸鍵只能包含:ascii 字符、ascii 數(shù)字、下劃線、短橫線。

import?toml

config?=?"""
key?=?"value"
bare_key?=?"value"
bare-key?=?"value"
#?1234?會被當(dāng)成字符串
1234?=?"value"??
"""

data?=?toml.loads(config)
print(data)
"""
{'key':?'value',?
?'bare_key':?'value',?
?'bare-key':?'value',?
?'1234':?'value'}
"""

如果不是裸鍵,那么就必須使用引號括起來,但是此時也支持我們使用更加廣泛的鍵名,但除了特殊場景,否則使用裸鍵是最佳實(shí)踐。

import?toml

config?=?"""
"127.0.0.1"?=?"value"
"character?encoding"?=?"value"
"???"?=?"value"
'key2'?=?"value"
'quoted?"value"'?=?"value"?
"""

data?=?toml.loads(config)
print(data)
"""
{'127.0.0.1':?'value',?
?'character?encoding':?'value',?
?'???':?'value',?
?'key2':?'value',?
?'quoted?"value"':?'value'}
"""

注意:裸鍵不能為空,但空引號鍵是允許的(雖然不建議如此)。

=?"沒有鍵名"??#?錯誤
""?=?"空"?????#?正確但不鼓勵
''?=?'空'?????#?正確但不鼓勵

然后是點(diǎn)分隔鍵,它是一系列通過點(diǎn)相連的裸鍵或引號鍵,這允許我們將相近屬性放在一起:

import?toml

config?=?"""
name?=?"橙子"
physical.color?=?"橙色"
physical.shape?=?"圓形"
site."google.com"?=?true
site.google.com?=?true
a.b.c.d?=?123
"""

data?=?toml.loads(config)
print(data)
"""
{
????'name':?'橙子',
????'physical':?{'color':?'橙色',
?????????????????'shape':?'圓形'},
????'site':?{'google.com':?True,
?????????????'google':?{'com':?True}},
????'a':?{'b':?{'c':?{'d':?123}}}
}
"""

我們看到這個點(diǎn)分隔符不錯喲,自動實(shí)現(xiàn)了嵌套結(jié)構(gòu),并且點(diǎn)分隔符周圍的空白會被忽略。

fruit.name?=?"香蕉"?????#?這是最佳實(shí)踐
fruit.?color?=?"黃色"????#?等同于?fruit.color
fruit?.?flavor?=?"香蕉"???#?等同于?fruit.flavor

注意:多次定義同一個鍵是不行的。

import?toml

config?=?"""
#?name?和?"name"?是等價的
name?=?"古明地覺"
"name"?=?"古明地戀"??
"""

try:
????data?=?toml.loads(config)
except?toml.decoder.TomlDecodeError?as?e:
????print(e)
"""
Duplicate?keys!?(line?4?column?1?char?36)
"""

對于點(diǎn)分隔鍵也是如此,只要一個鍵還沒有被直接定義過,我們就仍可以對它和它下屬的鍵名賦值。

import?toml

config?=?"""
fruit.apple.smooth?=?true#?此時可以繼續(xù)操作?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?的值定義為一個整數(shù)
fruit.apple?=?1
#?但接下來就不合法了,因?yàn)檎麛?shù)不能變成字典
fruit.apple.smooth?=?true

#?如果我們設(shè)置?fruit.apple?=?{},那么第二個賦值是可以的
#?沒錯,我們可以通過?{}?直接創(chuàng)建一個字典

可以看到,真的很像 Python。然后再來說一個特例:

import?toml

config?=?"""
3.14?=?"pi"??
"3.14"?=?"pi"??
"""

data?=?toml.loads(config)
print(data)
"""
{'3':?{'14':?'pi'},?'3.14':?'pi'}
"""

如果鍵是浮點(diǎn)數(shù),那么需要使用引號括起來,否則會被解釋為點(diǎn)分隔鍵。

看完了鍵,再來看看值(value),其實(shí)對于 toml 來說,值比鍵要簡單的多得多。

字符串

字符串共有四種方式來表示:基礎(chǔ)式的,多行基礎(chǔ)式的,字面量式的,和多行字面量式的。

1)基礎(chǔ)字符串由引號包裹,任何 Unicode 字符都可以使用,除了那些必須轉(zhuǎn)義的。

import?toml

config?=?"""
str?=?'我是一個字符串,"你可以把我引起來"'?
"""

data?=?toml.loads(config)
print(data)
"""
{'str':?'我是一個字符串,"你可以把我引起來"'}
"""

2)多行字符串由三個引號包裹,允許換行,注意:緊隨開頭引號的換行會被去除,其它空白和換行會被原樣保留。

import?toml

config?=?"""
str?=?'''
玫瑰是紅色的
紫羅蘭是藍(lán)色的
'''
"""

data?=?toml.loads(config)
print(data)
"""
{'str':?'玫瑰是紅色的\n紫羅蘭是藍(lán)色的\n'}
"""

這里的引號可以是雙引號、也可以是單引號。

整數(shù)

整數(shù)是純數(shù)字,正數(shù)可以有加號前綴,負(fù)數(shù)的前綴是減號。

import?toml

config?=?"""
int1?=?+99
int2?=?42
int3?=?0
int4?=?-17

#?對于大數(shù),可以在數(shù)字之間用下劃線來增強(qiáng)可讀性
#?每個下劃線兩側(cè)必須至少有一個數(shù)字。
int5?=?1_000
int6?=?5_349_221
int7?=?53_49_221??#?印度記數(shù)體系分組
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}
"""

但是注意:數(shù)字不能以零開頭,除了 0 本身。當(dāng)然 -0 與 +0 也是有效的,并等同于無前綴的零。非負(fù)整數(shù)值也可以用十六進(jìn)制、八進(jìn)制或二進(jìn)制來表示。

#?帶有?`0x`?前綴的十六進(jìn)制,大小寫均可
hex1?=?0xDEADBEEF
hex2?=?0xdeadbeef
hex3?=?0xdead_beef

#?帶有?`0o`?前綴的八進(jìn)制
oct1?=?0o01234567
oct2?=?0o755?#?對于表示?Unix?文件權(quán)限很有用

#?帶有?`0b`?前綴的二進(jìn)制
bin1?=?0b11010110

浮點(diǎn)數(shù)

一個浮點(diǎn)數(shù)由一個整數(shù)部分(遵從與十進(jìn)制整數(shù)值相同的規(guī)則)后跟上一個小數(shù)部分、或一個指數(shù)部分組成。如果小數(shù)部分和指數(shù)部分兼有,那小數(shù)部分必須在指數(shù)部分前面。

import?toml

config?=?"""
#?小數(shù)
flt1?=?+1.0
flt2?=?3.1415
flt3?=?-0.01

#?指數(shù)
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}
"""

小數(shù)部分是一個小數(shù)點(diǎn)后跟一個或多個數(shù)字,一個指數(shù)部分是一個 E(大小寫均可)后跟一個整數(shù)部分(遵從與十進(jìn)制整數(shù)值相同的規(guī)則,但可以包含前導(dǎo)零)。小數(shù)點(diǎn),如果有用到的話,每側(cè)必須緊鄰至少一個數(shù)字。

#?非法的浮點(diǎn)數(shù)
invalid_float_1?=?.7
invalid_float_2?=?7.
invalid_float_3?=?3.e+20

與整數(shù)相似,可以使用下劃線來增強(qiáng)可讀性,每個下劃線必須被至少一個數(shù)字圍繞。

flt8?=?224_617.445_991_228

浮點(diǎn)數(shù)值 -0.0 與 +0.0 是有效的,并且應(yīng)當(dāng)遵從 IEEE 754。特殊浮點(diǎn)值也能夠表示:

#?無窮
sf1?=?inf??#?正無窮
sf2?=?+inf?#?正無窮
sf3?=?-inf?#?負(fù)無窮

#?非數(shù)
sf4?=?nan??#?是對應(yīng)信號非數(shù)碼還是靜默非數(shù)碼,取決于實(shí)現(xiàn)
sf5?=?+nan?#?等同于?`nan`
sf6?=?-nan?#?正確,實(shí)際碼取決于實(shí)現(xiàn)

布爾值

布爾值就是慣用的那樣,但要小寫。

bool1?=?true
bool2?=?false

日期

可以是普通的 datetime,或者是遵循 ISO-8859-1 格式的日期。

import?toml

config?=?"""
dt1?=?2020-01-01T12:33:22+00:00
dt2?=?2020-11-12?12:11:33
dt3?=?2020-11-23
"""

data?=?toml.loads(config)
print(data)
"""
{'dt1':?datetime.datetime(2020,?1,?1,?12,?33,?22,?tzinfo=...),?
?'dt2':?datetime.datetime(2020,?11,?12,?12,?11,?33),?
?'dt3':?datetime.date(2020,?11,?23)}
"""

數(shù)組

語法和 Python 的列表類似:

import?toml

config?=?"""
#?每個數(shù)組里面的元素類型要一致
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]}
"""

數(shù)組可以跨行,數(shù)組的最后一個值后面可以有終逗號(也稱為尾逗號)。

import?toml

config?=?"""
integers2?=?[
??1,?2,?3
]

integers3?=?[
??1,
??2,?#?這是可以的
]
"""

data?=?toml.loads(config)
print(data)
"""
{'integers2':?[1,?2,?3],?'integers3':?[1,?2]}
"""

表,完全可以把它想象成 ini 的 section。

import?toml

config?=?"""
#?表名的定義規(guī)則與鍵名相同
#?解析之后得到的大字典中就有?"table-1"?這個?key
#?并且其?value?也是一個表,在它下方
#?直至下一個表頭或文件結(jié)束,都是這個表內(nèi)部的鍵值對
[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}}
"""

但是我們之前也實(shí)現(xiàn)過類似于這種結(jié)構(gòu),沒錯,就是點(diǎn)分隔符:

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}}
}
"""

估計你已經(jīng)猜到了,它們被當(dāng)成了 'table-2' 對應(yīng)的字典里面的 key 了。此外我們還可以將上面兩種方式結(jié)合起來:

import?toml

config?=?"""
#?[]?里面的不再是一個普通的鍵,而是點(diǎn)分隔鍵
#?另外鍵名周圍的空格會被忽略,但是最好不要有
[dog??.??"tater.man"]??
type.name?=?"哈巴狗"
"""

data?=?toml.loads(config)
print(data)
"""
{
????'dog':?{'tater.man':?{'type':?{'name':?'哈巴狗'}}}
}
"""

表的里面也是可以沒有鍵值對的:

import?toml

config?=?"""
[x.y.z.w.a.n]

[x.m]

[x.n]

[x]
a.b.c?=?"xxx"
"""

data?=?toml.loads(config)
print(data)
"""
{'x':
????{
????????'a':?{'b':?{'c':?'xxx'}},
????????'m':?{},
????????'n':?{},
????????'y':?{'z':?{'w':?{'a':?{'n':?{}}}}}
????}
}
"""

總的來說還是蠻強(qiáng)大的,但是要注意:不能重復(fù)定義。

行內(nèi)表

行內(nèi)表提供了一種更為緊湊的語法來表示表,因?yàn)樯厦婷恳粋€鍵值對都需要單獨(dú)寫一行,比如:

[table1]
a?=?1
b?=?2
c?=?3
#?最終可以得到?
#?{'table1':?{'a':?1,?'b':?2,?'c':?3}}

但是除了上面的表達(dá)方式之外,我們還可以采用行內(nèi)表:

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'}}}
}
"""

表數(shù)組

然后來看看數(shù)組和表的結(jié)合:

import?toml

config?=?"""
[name1]
girl?=?"古明地覺"

[[name2]]
girl?=?"古明地戀"

[name3]
[[name4]]
"""

data?=?toml.loads(config)
print(data)
"""
{'name1':?{'girl':?'古明地覺'},
?'name2':?[{'girl':?'古明地戀'}],
?'name3':?{},
?'name4':?[{}]}
"""

當(dāng)使用 [[]] 的時候,相當(dāng)于在 [] 的基礎(chǔ)上套上一層列表。并且任何對表數(shù)組的引用都指向該數(shù)組里最近定義的表元素,這允許我們在最近的表內(nèi)定義子表,甚至子表數(shù)組。

我們再舉個更復(fù)雜的例子:

import?toml

config?=?"""
[[fruits]]??
name?=?"蘋果"??

#?會操作?[]?里面最近定義的?{}
[fruits.physical]??
color?=?"紅色"
shape?=?"圓形"

[[fruits.varieties]]??#?嵌套表數(shù)組
name?=?"蛇果"????

[[fruits.varieties]]
name?=?"澳洲青蘋"?

[[fruits]]
name?=?"香蕉"?

[[fruits.varieties]]
name?=?"車前草"??
"""

data?=?toml.loads(config)
print(data)
"""
{
????'fruits':
????????[
????????????{
????????????????'name':?'蘋果',
????????????????'physical':?{'color':?'紅色',?
?????????????????????????????'shape':?'圓形'},
????????????????'varieties':?[{'name':?'蛇果'},?
??????????????????????????????{'name':?'澳洲青蘋'}]
????????????},
????????????{
????????????????'name':?'香蕉',?
????????????????'varieties':?[{'name':?'車前草'}]
????????????}
????????]
}
"""

很明顯這種定義不是很常用,配置文件應(yīng)該要非常直觀才對,但這已經(jīng)不是很好理解了。

以上就是Python解析toml配置文件的方法分享的詳細(xì)內(nèi)容,更多關(guān)于Python解析toml的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論