Python實(shí)現(xiàn)解析yaml配置文件的示例詳解
楔子
前面我們介紹了 ini 格式的配置文件,本次來(lái)看看 yaml,它的表達(dá)能力相比 ini 更加的強(qiáng)大。yaml 文件以 .yml 結(jié)尾,在介紹它的語(yǔ)法結(jié)構(gòu)之前我們先來(lái)看看 yaml 的一些基本規(guī)則。
- 大小寫敏感;
- 使用縮進(jìn)表示層級(jí)關(guān)系,并且縮進(jìn)只能用空格、不可以使用 tab 鍵??s進(jìn)的空格數(shù)目不重要,只要相同層級(jí)的元素左側(cè)對(duì)齊即可;
- # 表示注釋,# 到行尾的所有字符都會(huì)被忽略;
yaml 支持的數(shù)據(jù)結(jié)構(gòu)有以下三種:
- 字典:鍵值對(duì)的集合;
- 數(shù)組:多個(gè)元素組成的集合;
- 標(biāo)量:?jiǎn)蝹€(gè)、不可分割的值;
Python 解析 yaml 則是通過(guò)一個(gè)名為 pyyaml 的庫(kù),直接 pip install pyyaml 即可。
下面我們來(lái)介紹一下 yaml 的數(shù)據(jù)結(jié)構(gòu)。
字典
類似于 Python 的字典,使用鍵值對(duì)表示:
name:?satori #?或者寫成下面的形式 {name:?satori}
Python 解析之后會(huì)是什么結(jié)果呢?
import?yaml config?=?""" name:?satori """ # yaml.safe_load:只解析自己信任的輸入 # yaml.unsafe_load:不檢測(cè)輸入的安全性 print(yaml.safe_load(config)) """ {'name':?'satori'} """ config?=?""" {name:?satori} """ print(yaml.safe_load(config)) """ {'name':?'satori'} """
在 yaml 里面,字典的 value 也可以是一個(gè)字典:
info:?{name:?satori,?address:?東方地靈殿}
Python 解析的結(jié)果如下:
import?yaml config?=?""" info:?{name:?satori,?address:?東方地靈殿} """ print(yaml.safe_load(config)) """ { ??'info':?{'name':?'satori',? ???????????'address':?'東方地靈殿'} } """
還是很簡(jiǎn)單的。
數(shù)組
一組連字符開頭的行,構(gòu)成一個(gè)數(shù)組。
-?古明地覺(jué) -?古明地戀 -?霧雨魔理沙 #?-?后面要有空格 #?或者寫成下面的形式 [古明地覺(jué),?古明地戀,?霧雨魔理沙]
Python 解析的結(jié)果如下:
import?yaml config?=?""" -?古明地覺(jué) -?古明地戀 -?霧雨魔理沙 """ print(yaml.safe_load(config)) """ ['古明地覺(jué)',?'古明地戀',?'霧雨魔理沙'] """ config?=?""" [古明地覺(jué),?古明地戀,?霧雨魔理沙] """ print(yaml.safe_load(config)) """ ['古明地覺(jué)',?'古明地戀',?'霧雨魔理沙'] """
并且數(shù)組的子成員也可以是一個(gè)數(shù)組:
-
- 古明地覺(jué)
- 古明地戀
- 霧雨魔理沙
Python 解析的結(jié)果如下:
import?yaml config?=?""" - ??-?古明地覺(jué) ??-?古明地戀 ??-?霧雨魔理沙 """ print(yaml.safe_load(config)) """ [['古明地覺(jué)',?'古明地戀',?'霧雨魔理沙']] """ #?更簡(jiǎn)潔的寫法 config?=?""" -?[古明地覺(jué),?古明地戀,?霧雨魔理沙] """ print(yaml.safe_load(config)) """ [['古明地覺(jué)',?'古明地戀',?'霧雨魔理沙']] """
顯然數(shù)組也可以放在字典中:
#?縮進(jìn)對(duì)應(yīng)的空格數(shù)沒(méi)有要求,但是必須一樣 #?對(duì)于當(dāng)前這個(gè)鍵值對(duì)而言也可以沒(méi)有縮進(jìn) girl: ????-?古明地覺(jué) ????-?古明地戀 ????-?霧雨魔理沙 #?或者下面這種形式 girl:?[古明地覺(jué),?古明地戀,?霧雨魔理沙] #?或者下面這種形式 {girl:?[古明地覺(jué),?古明地戀,?霧雨魔理沙]}
Python 解析的結(jié)果如下:
import?yaml config?=?""" girl: ??-?古明地覺(jué) ??-?古明地戀 ??-?霧雨魔理沙 """ print(yaml.safe_load(config)) """ {'girl':?['古明地覺(jué)',?'古明地戀',?'霧雨魔理沙']} """ #?注意:上面的 girl 對(duì)應(yīng)的是數(shù)組 #?因?yàn)槊總€(gè)元素前面都有?- #?但如果沒(méi)有的話會(huì)發(fā)生什么? config?=?""" girl: ????古明地覺(jué) ????古明地戀 ????霧雨魔理沙 """ print(yaml.safe_load(config)) """ {'girl':?'古明地覺(jué)?古明地戀?霧雨魔理沙'} """ #?我們看到整體相當(dāng)于是一個(gè)字符串 #?類似于?html,之間用一個(gè)空格代替 #?因此如果內(nèi)容比較長(zhǎng),我們可以寫成多行 #?但是注意:每一行前面必須有空格
然后是一個(gè)稍微復(fù)雜的例子:
import?yaml config?=?""" girl: ????#?會(huì)對(duì)應(yīng)一個(gè)數(shù)組 ????-?古明地覺(jué) ????-?古明地戀 ????-?霧雨魔理沙 ???? place1: ????#?雖然不是數(shù)組,但是內(nèi)部是字典的形式 ????#?所以會(huì)對(duì)應(yīng)一個(gè)含有三個(gè)鍵值對(duì)的字典 ????古明地覺(jué):?東方地靈殿 ????古明地戀:?東方地靈殿 ????霧雨魔理沙:?魔法森林 place2: ??#?是數(shù)組,數(shù)組里面每個(gè)元素是一個(gè)字典 ??-?古明地覺(jué):?東方地靈殿 ??-?古明地戀:?東方地靈殿 ??-?霧雨魔理沙:?魔法森林 """ print(yaml.safe_load(config)) """ { ????'girl':?['古明地覺(jué)',?'古明地戀',?'霧雨魔理沙'], ????'place1':?{'古明地覺(jué)':?'東方地靈殿',? ???????????????'古明地戀':?'東方地靈殿',? ???????????????'霧雨魔理沙':?'魔法森林'}, ????'place2':?[{'古明地覺(jué)':?'東方地靈殿'},? ???????????????{'古明地戀':?'東方地靈殿'},? ???????????????{'霧雨魔理沙':?'魔法森林'}] } """
place1 對(duì)應(yīng)的是一個(gè)字典,place2 對(duì)應(yīng)的是一個(gè)數(shù)組。
標(biāo)量
標(biāo)量屬于最基本的、不可再分的值,比較簡(jiǎn)單,我們就全部都說(shuō)了吧。
import?yaml config?=?""" int:?123 float:?3.14 bool: ????-?true? ????-?false #?波浪號(hào)表示空???? NoneType:?~?? datetime:?2020-11-11?12:12:13 #?使用兩個(gè)?!?可以進(jìn)行類型強(qiáng)轉(zhuǎn) #?不過(guò)幾乎用不到? cast: ????-?!!str?123 ????-?!!str?true?? """ print(yaml.safe_load(config)) """ { ????'int':?123,?'float':?3.14, ????'bool':?[True,?False],?'NoneType':?None, ????'datetime':?datetime.datetime(2020,?11,?11,?12,?12,?13),? ????'cast':?['123',?'true'] } """
這里可能有人已經(jīng)發(fā)現(xiàn)了,就是字符串不需要加引號(hào),但如果里面有特殊字符怎么辦?所以 yaml 是支持使用引號(hào)括起來(lái)的。
import?yaml config?=?""" name1:?古明地覺(jué)??????a?x???$?#??!!???????? name2:?"古明地覺(jué)??????a?x???$?#??!!"???????? name3:?'古明地覺(jué)??????a?x???$?#??!!'??? """ print(yaml.safe_load(config)) """ {'name1':?'古明地覺(jué)??????a?x???$',? ?'name2':?'古明地覺(jué)??????a?x???$?#??!!',? ?'name3':?'古明地覺(jué)??????a?x???$?#??!!'} """
對(duì)于 yaml 而言,字符串默認(rèn)是從第一個(gè)不是空格的字符、匹配到最后一個(gè)不是空格的字符(如果遇到 # 直接停止)。因此如果 value 的前面或后面有空格的話,那么這些空格是不會(huì)顯示的,或者當(dāng)中有 #,那么 # 后面的內(nèi)容也不會(huì)顯示。
解決辦法是使用單引號(hào)或雙引號(hào)括起來(lái),如果內(nèi)部還有引號(hào),那么需要輸入兩遍進(jìn)行轉(zhuǎn)義(如果內(nèi)部的引號(hào)和外面括起來(lái)的引號(hào)相同的話)。
引用
對(duì)于 yaml 而言,還支持我們采用 & 和 * 進(jìn)行引用,舉個(gè)例子:
import?yaml config?=?""" #?多了一個(gè)?&db_info_ref #?相當(dāng)于起了個(gè)名字,叫?db_info_ref db_info:?&db_info_ref?? ????host:?127.0.0.1 ????port:?5432 ????user:?postgres ????password:?123456 deploy: ????os:?Linux ????#?將內(nèi)容直接扔到里面來(lái)?? ????<<:?*db_info_ref?? """ print(yaml.safe_load(config)) """ { ????'db_info':?{'host':?'127.0.0.1', ????????????????'port':?5432, ????????????????'user':?'postgres', ????????????????'password':?123456}, ????'deploy':?{'host':?'127.0.0.1', ???????????????'port':?5432, ???????????????'user':?'postgres', ???????????????'password':?123456, ???????????????'os':?'Linux'} } """
& 用來(lái)建立錨點(diǎn),<< 表示合并當(dāng)前數(shù)據(jù),* 表示用來(lái)引用錨點(diǎn)。還可以作用在數(shù)組中:
import?yaml config?=?""" -?&name?古明地覺(jué)? -?古明地戀 -?霧雨魔理沙 -?*name """ print(yaml.safe_load(config)) """ ['古明地覺(jué)',?'古明地戀',? ?'霧雨魔理沙',?'古明地覺(jué)'] """
生成 yaml 文件
既然能夠讀取 yaml 文件,那么自然也能生成 yaml 文件。
import?yaml data?=?{ ????"girl":?[ ????????{"name":?"古明地覺(jué)",?"age":?17,?"place":?"東方地靈殿"}, ????????{"name":?"古明地戀",?"age":?16,?"place":?"東方地靈殿"}, ????????{"name":?"霧雨魔理沙",?"age":?16,?"place":?"魔法森林"} ????], ????"other":?{ ????????"古明地覺(jué)":?{"nickname":?["小五",?"少女覺(jué)",?"覺(jué)大人",?"小五蘿莉"], ?????????????????"length":?155}, ????????"古明地戀":?{"nickname":?["戀戀"],?"length":?155}, ????????"霧雨魔理沙":?{"nickname":?["摸你傻"],?"length":?155} ????} } with?open("cfg.yml",?"w",?encoding="utf-8")?as?f: ????yaml.dump(data,?f,?allow_unicode=True,?indent=2)
然后我們看看生成的 yml 文件長(zhǎng)什么樣子。
我們來(lái)看 yml 文件,然后反推出相應(yīng)的數(shù)據(jù)結(jié)構(gòu)。首先整體是一個(gè)字典,里面有 girl 和 other 兩個(gè) key。其中 girl 對(duì)應(yīng)一個(gè)數(shù)組,數(shù)組里面每個(gè)元素都是字典,這是符合預(yù)期的。
然后 other 對(duì)應(yīng)一個(gè)字典,而且這個(gè)字典內(nèi)部有三個(gè)鍵值對(duì),key 分別是:古明地覺(jué)、古明地戀、霧雨魔理沙,各自對(duì)應(yīng)的 value 又是一個(gè)字典(內(nèi)部有 length、nickname 兩個(gè) key,length 對(duì)應(yīng)整型、nickname 對(duì)應(yīng)列表)。
最后再看一個(gè)本人之前項(xiàng)目中的 yml 文件,可以猜猜看解析出來(lái)長(zhǎng)什么樣子。
解析一下看看和你想的是不是一樣的。
import?yaml with?open(".gitlab-ci.yml",?"r",?encoding="utf-8")?as?f: ????data?=?f.read() data?=?yaml.safe_load(data) print(data) """ { ????'stages':?['test'],? ????'cache':?{'key':?'${CI_COMMIT_REF_SLUG}',? ??????????????'paths':?['.cache/pip']}, ????'variables':?{'PIP_CACHE_DIR':?'$CI_PROJECT_DIR/.cache/pip'}, ????'test':?{'stage':?'test',? ?????????????'image':?'xxxxxxx/python:3.8.1-thanosclient-buster',? ?????????????'only':?['branches',?'tags'], ?????????????'services':?['mysql:5.7'], ?????????????'variables':?{'PROJECT':?'XXXXXX',? ???????????????????????????'PIP_CACHE_DIR':?'$CI_PROJECT_DIR/.cache/pip', ???????????????????????????'MARKETING_CONFIG':?'config/room/ci.cn-gz.toml', ???????????????????????????'MYSQL_DATABASE':?'activity',? ???????????????????????????'MYSQL_ROOT_PASSWORD':?'password', ???????????????????????????'MYSQL_INITDB_SKIP_TZINFO':?'1'} ?????????????} } """
結(jié)果應(yīng)該不難想,畢竟 yaml 文件不是很復(fù)雜。
以上就是Python實(shí)現(xiàn)解析yaml配置文件的示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Python解析yaml配置文件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python 自動(dòng)刷新網(wǎng)頁(yè)的兩種方法
這篇文章主要介紹了python 自動(dòng)刷新網(wǎng)頁(yè)的兩種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04Python實(shí)現(xiàn)的簡(jiǎn)單文件傳輸服務(wù)器和客戶端
這篇文章主要介紹了Python實(shí)現(xiàn)的簡(jiǎn)單文件傳輸服務(wù)器和客戶端,本文直接給出Server和Client端的實(shí)現(xiàn)代碼,需要的朋友可以參考下2015-04-04可用于監(jiān)控 mysql Master Slave 狀態(tài)的python代碼
用于監(jiān)控MySQL Master Slave 狀態(tài)的python代碼,有需要的朋友可以參考下2013-02-02python實(shí)現(xiàn)跨進(jìn)程(跨py文件)通信示例
本文主要介紹了python實(shí)現(xiàn)跨進(jìn)程(跨py文件)通信示例,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03matplotlib 對(duì)坐標(biāo)的控制,加圖例注釋的操作
這篇文章主要介紹了matplotlib 對(duì)坐標(biāo)的控制,加圖例注釋的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-04-04詳解Python實(shí)現(xiàn)字典合并的四種方法
這篇文章主要為大家詳細(xì)介紹了Python的合并字典的四種方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-03-03