欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

楔子

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

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

舉個(gè)例子

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

import?toml

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

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

[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 格式字符串并寫(xiě)入文件中
data?=?toml.loads(config)
print(data)
"""
{
????'title':?'toml?小栗子',?
????'owner':?{'name':?'古明地覺(jué)',?
??????????????'age':?17,?
??????????????'place':?'東方地靈殿',?
??????????????'nickname':?['小五',?'少女覺(jué)',?'覺(jué)大人']},
????'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)行配置,然后也有類(lèi)似于 ini 里面的 section,每個(gè) section 都是字典中的一個(gè) key,然后該 key 也對(duì)應(yīng)一個(gè)字典。但是我們注意看最開(kāi)始的 title,由于它上面沒(méi)有 section,所以它是一個(gè)單獨(dú)的 key。

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

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

toml 文件是大小寫(xiě)敏感的;

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

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

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

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

注釋

toml 采用 # 表示注釋?zhuān)e個(gè)例子:

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

可以解析一下看看會(huì)得到什么,劇透:會(huì)得到只包含一個(gè)鍵值對(duì)的字典。

鍵值對(duì)

TOML 文檔最基本的構(gòu)成區(qū)塊是鍵值對(duì),鍵名在等號(hào)的左邊、值在右邊,并且鍵名和鍵值周?chē)目瞻讜?huì)被忽略。此外鍵、等號(hào)和值必須在同一行(不過(guò)有些值可以跨多行)。

key?=?"value"

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

import?toml

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

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

如果不是裸鍵,那么就必須使用引號(hào)括起來(lái),但是此時(shí)也支持我們使用更加廣泛的鍵名,但除了特殊場(chǎng)景,否則使用裸鍵是最佳實(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'}
"""

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

=?"沒(méi)有鍵名"??#?錯(cuò)誤
""?=?"空"?????#?正確但不鼓勵(lì)
''?=?'空'?????#?正確但不鼓勵(lì)

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

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

我們看到這個(gè)點(diǎn)分隔符不錯(cuò)喲,自動(dòng)實(shí)現(xiàn)了嵌套結(jié)構(gòu),并且點(diǎn)分隔符周?chē)目瞻讜?huì)被忽略。

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

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

import?toml

config?=?"""
#?name?和?"name"?是等價(jià)的
name?=?"古明地覺(jué)"
"name"?=?"古明地戀"??
"""

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

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

import?toml

config?=?"""
fruit.apple.smooth?=?true#?此時(shí)可以繼續(xù)操作?fruit、fruit.apple,它們都是字典
#?給?fruit?這個(gè)字典加一個(gè)?key??
fruit.orange?=?2??
#?給?fruit.apple?加一個(gè)?key
fruit.apple.color?=?"red"???
"""

data?=?toml.loads(config)
print(data)
"""
{
????'fruit':?{'apple':?{'smooth':?True,?
????????????????????????'color':?'red'},?
??????????????'orange':?2}
}
"""

但下面這個(gè)操作是不行的:

#?將?fruit.apple?的值定義為一個(gè)整數(shù)
fruit.apple?=?1
#?但接下來(lái)就不合法了,因?yàn)檎麛?shù)不能變成字典
fruit.apple.smooth?=?true

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

可以看到,真的很像 Python。然后再來(lái)說(shuō)一個(gè)特例:

import?toml

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

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

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

看完了鍵,再來(lái)看看值(value),其實(shí)對(duì)于 toml 來(lái)說(shuō),值比鍵要簡(jiǎn)單的多得多。

字符串

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

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

import?toml

config?=?"""
str?=?'我是一個(gè)字符串,"你可以把我引起來(lái)"'?
"""

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

2)多行字符串由三個(gè)引號(hào)包裹,允許換行,注意:緊隨開(kāi)頭引號(hào)的換行會(huì)被去除,其它空白和換行會(huì)被原樣保留。

import?toml

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

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

這里的引號(hào)可以是雙引號(hào)、也可以是單引號(hào)。

整數(shù)

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

import?toml

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

#?對(duì)于大數(shù),可以在數(shù)字之間用下劃線來(lái)增強(qiáng)可讀性
#?每個(gè)下劃線兩側(cè)必須至少有一個(gè)數(shù)字。
int5?=?1_000
int6?=?5_349_221
int7?=?53_49_221??#?印度記數(shù)體系分組
int8?=?1_2_3_4_5??#?無(wú)誤但不鼓勵(lì)
"""

data?=?toml.loads(config)
print(data)
"""
{'int1':?99,
?'int2':?42,
?'int3':?0,
?'int4':?-17,
?'int5':?1000,
?'int6':?5349221,
?'int7':?5349221,
?'int8':?12345}
"""

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

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

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

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

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

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

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

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

flt8?=?224_617.445_991_228

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

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

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

布爾值

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

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ù)組

語(yǔ)法和 Python 的列表類(lèi)似:

import?toml

config?=?"""
#?每個(gè)數(shù)組里面的元素類(lèi)型要一致
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ù)組的最后一個(gè)值后面可以有終逗號(hào)(也稱(chēng)為尾逗號(hào))。

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"?這個(gè)?key
#?并且其?value?也是一個(gè)表,在它下方
#?直至下一個(gè)表頭或文件結(jié)束,都是這個(gè)表內(nèi)部的鍵值對(duì)
[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)過(guò)類(lèi)似于這種結(jié)構(gòu),沒(méi)錯(cuò),就是點(diǎn)分隔符:

import?toml

config?=?"""
#?所以?other-table-1?和?table-1?是等價(jià)的
#?other-table-2?和?table-2?是等價(jià)的
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}}
"""

不過(guò)注意:我們必須要把 other-table-1 和 other-table-2 定義在上面,如果我們定義在下面看看會(huì)有什么后果:

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ì)你已經(jīng)猜到了,它們被當(dāng)成了 'table-2' 對(duì)應(yīng)的字典里面的 key 了。此外我們還可以將上面兩種方式結(jié)合起來(lái):

import?toml

config?=?"""
#?[]?里面的不再是一個(gè)普通的鍵,而是點(diǎn)分隔鍵
#?另外鍵名周?chē)目崭駮?huì)被忽略,但是最好不要有
[dog??.??"tater.man"]??
type.name?=?"哈巴狗"
"""

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

表的里面也是可以沒(méi)有鍵值對(duì)的:

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':?{}}}}}
????}
}
"""

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

行內(nèi)表

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

[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ù)組

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

import?toml

config?=?"""
[name1]
girl?=?"古明地覺(jué)"

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

[name3]
[[name4]]
"""

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

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

我們?cè)倥e個(gè)更復(fù)雜的例子:

import?toml

config?=?"""
[[fruits]]??
name?=?"蘋(píng)果"??

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

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

[[fruits.varieties]]
name?=?"澳洲青蘋(píng)"?

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

[[fruits.varieties]]
name?=?"車(chē)前草"??
"""

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

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

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

相關(guān)文章

最新評(píng)論