<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
上一篇文章我們介紹了 yaml,雖然 yaml 的表達能力已經很豐富了,但 GitHub 覺得還是不夠優雅,所以鼓搗出了一個 toml。toml 有著比 yaml 更簡潔的語法,它的目標就是成為一個最簡單的組態檔格式。
然後 Python 解析 toml 檔案需要使用一個名字也叫 toml 的庫,直接 pip install 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組態檔的方法分享的詳細內容,更多關於Python解析toml的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45