您好,登錄后才能下訂單哦!
本篇內容介紹了“怎么用Python解析toml配置文件”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
有了 ini 和 yaml,相信 toml 學習來也很簡單,先直接看一個例子吧。
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 的形式進行配置,然后也有類似于 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 = """ "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'} """
注意:裸鍵不能為空,但空引號鍵是允許的(雖然不建議如此)。
= "沒有鍵名" # 錯誤 "" = "空" # 正確但不鼓勵 '' = '空' # 正確但不鼓勵
然后是點分隔鍵,它是一系列通過點相連的裸鍵或引號鍵,這允許我們將相近屬性放在一起:
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}}} } """
我們看到這個點分隔符不錯喲,自動實現了嵌套結構,并且點分隔符周圍的空白會被忽略。
fruit.name = "香蕉" # 這是最佳實踐 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) """
對于點分隔鍵也是如此,只要一個鍵還沒有被直接定義過,我們就仍可以對它和它下屬的鍵名賦值。
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 是有效的,并且應當遵從 IEEE 754。特殊浮點值也能夠表示:
# 無窮 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 = 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)} """
語法和 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 = [ 1, 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"] 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': {}}}}} } } """
總的來說還是蠻強大的,但是要注意:不能重復定義。
行內表提供了一種更為緊湊的語法來表示表,因為上面每一個鍵值對都需要單獨寫一行,比如:
[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 toml config = """ [name1] girl = "古明地覺" [[name2]] girl = "古明地戀" [name3] [[name4]] """ data = toml.loads(config) print(data) """ {'name1': {'girl': '古明地覺'}, 'name2': [{'girl': '古明地戀'}], 'name3': {}, 'name4': [{}]} """
當使用 [[]] 的時候,相當于在 [] 的基礎上套上一層列表。并且任何對表數組的引用都指向該數組里最近定義的表元素,這允許我們在最近的表內定義子表,甚至子表數組。
我們再舉個更復雜的例子:
import toml config = """ [[fruits]] name = "蘋果" # 會操作 [] 里面最近定義的 {} [fruits.physical] color = "紅色" shape = "圓形" [[fruits.varieties]] # 嵌套表數組 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': '車前草'}] } ] } """
很明顯這種定義不是很常用,配置文件應該要非常直觀才對,但這已經不是很好理解了。
“怎么用Python解析toml配置文件”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。