Python實現(xiàn)解析yaml配置文件的示例詳解
楔子
前面我們介紹了 ini 格式的配置文件,本次來看看 yaml,它的表達能力相比 ini 更加的強大。yaml 文件以 .yml 結尾,在介紹它的語法結構之前我們先來看看 yaml 的一些基本規(guī)則。
- 大小寫敏感;
- 使用縮進表示層級關系,并且縮進只能用空格、不可以使用 tab 鍵??s進的空格數(shù)目不重要,只要相同層級的元素左側對齊即可;
- # 表示注釋,# 到行尾的所有字符都會被忽略;
yaml 支持的數(shù)據(jù)結構有以下三種:
- 字典:鍵值對的集合;
- 數(shù)組:多個元素組成的集合;
- 標量:單個、不可分割的值;
Python 解析 yaml 則是通過一個名為 pyyaml 的庫,直接 pip install pyyaml 即可。
下面我們來介紹一下 yaml 的數(shù)據(jù)結構。
字典
類似于 Python 的字典,使用鍵值對表示:
name:?satori #?或者寫成下面的形式 {name:?satori}
Python 解析之后會是什么結果呢?
import?yaml config?=?""" name:?satori """ # yaml.safe_load:只解析自己信任的輸入 # yaml.unsafe_load:不檢測輸入的安全性 print(yaml.safe_load(config)) """ {'name':?'satori'} """ config?=?""" {name:?satori} """ print(yaml.safe_load(config)) """ {'name':?'satori'} """
在 yaml 里面,字典的 value 也可以是一個字典:
info:?{name:?satori,?address:?東方地靈殿}
Python 解析的結果如下:
import?yaml config?=?""" info:?{name:?satori,?address:?東方地靈殿} """ print(yaml.safe_load(config)) """ { ??'info':?{'name':?'satori',? ???????????'address':?'東方地靈殿'} } """
還是很簡單的。
數(shù)組
一組連字符開頭的行,構成一個數(shù)組。
-?古明地覺 -?古明地戀 -?霧雨魔理沙 #?-?后面要有空格 #?或者寫成下面的形式 [古明地覺,?古明地戀,?霧雨魔理沙]
Python 解析的結果如下:
import?yaml config?=?""" -?古明地覺 -?古明地戀 -?霧雨魔理沙 """ print(yaml.safe_load(config)) """ ['古明地覺',?'古明地戀',?'霧雨魔理沙'] """ config?=?""" [古明地覺,?古明地戀,?霧雨魔理沙] """ print(yaml.safe_load(config)) """ ['古明地覺',?'古明地戀',?'霧雨魔理沙'] """
并且數(shù)組的子成員也可以是一個數(shù)組:
-
- 古明地覺
- 古明地戀
- 霧雨魔理沙
Python 解析的結果如下:
import?yaml config?=?""" - ??-?古明地覺 ??-?古明地戀 ??-?霧雨魔理沙 """ print(yaml.safe_load(config)) """ [['古明地覺',?'古明地戀',?'霧雨魔理沙']] """ #?更簡潔的寫法 config?=?""" -?[古明地覺,?古明地戀,?霧雨魔理沙] """ print(yaml.safe_load(config)) """ [['古明地覺',?'古明地戀',?'霧雨魔理沙']] """
顯然數(shù)組也可以放在字典中:
#?縮進對應的空格數(shù)沒有要求,但是必須一樣 #?對于當前這個鍵值對而言也可以沒有縮進 girl: ????-?古明地覺 ????-?古明地戀 ????-?霧雨魔理沙 #?或者下面這種形式 girl:?[古明地覺,?古明地戀,?霧雨魔理沙] #?或者下面這種形式 {girl:?[古明地覺,?古明地戀,?霧雨魔理沙]}
Python 解析的結果如下:
import?yaml config?=?""" girl: ??-?古明地覺 ??-?古明地戀 ??-?霧雨魔理沙 """ print(yaml.safe_load(config)) """ {'girl':?['古明地覺',?'古明地戀',?'霧雨魔理沙']} """ #?注意:上面的 girl 對應的是數(shù)組 #?因為每個元素前面都有?- #?但如果沒有的話會發(fā)生什么? config?=?""" girl: ????古明地覺 ????古明地戀 ????霧雨魔理沙 """ print(yaml.safe_load(config)) """ {'girl':?'古明地覺?古明地戀?霧雨魔理沙'} """ #?我們看到整體相當于是一個字符串 #?類似于?html,之間用一個空格代替 #?因此如果內(nèi)容比較長,我們可以寫成多行 #?但是注意:每一行前面必須有空格
然后是一個稍微復雜的例子:
import?yaml config?=?""" girl: ????#?會對應一個數(shù)組 ????-?古明地覺 ????-?古明地戀 ????-?霧雨魔理沙 ???? place1: ????#?雖然不是數(shù)組,但是內(nèi)部是字典的形式 ????#?所以會對應一個含有三個鍵值對的字典 ????古明地覺:?東方地靈殿 ????古明地戀:?東方地靈殿 ????霧雨魔理沙:?魔法森林 place2: ??#?是數(shù)組,數(shù)組里面每個元素是一個字典 ??-?古明地覺:?東方地靈殿 ??-?古明地戀:?東方地靈殿 ??-?霧雨魔理沙:?魔法森林 """ print(yaml.safe_load(config)) """ { ????'girl':?['古明地覺',?'古明地戀',?'霧雨魔理沙'], ????'place1':?{'古明地覺':?'東方地靈殿',? ???????????????'古明地戀':?'東方地靈殿',? ???????????????'霧雨魔理沙':?'魔法森林'}, ????'place2':?[{'古明地覺':?'東方地靈殿'},? ???????????????{'古明地戀':?'東方地靈殿'},? ???????????????{'霧雨魔理沙':?'魔法森林'}] } """
place1 對應的是一個字典,place2 對應的是一個數(shù)組。
標量
標量屬于最基本的、不可再分的值,比較簡單,我們就全部都說了吧。
import?yaml config?=?""" int:?123 float:?3.14 bool: ????-?true? ????-?false #?波浪號表示空???? NoneType:?~?? datetime:?2020-11-11?12:12:13 #?使用兩個?!?可以進行類型強轉 #?不過幾乎用不到? 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)了,就是字符串不需要加引號,但如果里面有特殊字符怎么辦?所以 yaml 是支持使用引號括起來的。
import?yaml config?=?""" name1:?古明地覺??????a?x???$?#??!!???????? name2:?"古明地覺??????a?x???$?#??!!"???????? name3:?'古明地覺??????a?x???$?#??!!'??? """ print(yaml.safe_load(config)) """ {'name1':?'古明地覺??????a?x???$',? ?'name2':?'古明地覺??????a?x???$?#??!!',? ?'name3':?'古明地覺??????a?x???$?#??!!'} """
對于 yaml 而言,字符串默認是從第一個不是空格的字符、匹配到最后一個不是空格的字符(如果遇到 # 直接停止)。因此如果 value 的前面或后面有空格的話,那么這些空格是不會顯示的,或者當中有 #,那么 # 后面的內(nèi)容也不會顯示。
解決辦法是使用單引號或雙引號括起來,如果內(nèi)部還有引號,那么需要輸入兩遍進行轉義(如果內(nèi)部的引號和外面括起來的引號相同的話)。
引用
對于 yaml 而言,還支持我們采用 & 和 * 進行引用,舉個例子:
import?yaml config?=?""" #?多了一個?&db_info_ref #?相當于起了個名字,叫?db_info_ref db_info:?&db_info_ref?? ????host:?127.0.0.1 ????port:?5432 ????user:?postgres ????password:?123456 deploy: ????os:?Linux ????#?將內(nè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'} } """
& 用來建立錨點,<< 表示合并當前數(shù)據(jù),* 表示用來引用錨點。還可以作用在數(shù)組中:
import?yaml config?=?""" -?&name?古明地覺? -?古明地戀 -?霧雨魔理沙 -?*name """ print(yaml.safe_load(config)) """ ['古明地覺',?'古明地戀',? ?'霧雨魔理沙',?'古明地覺'] """
生成 yaml 文件
既然能夠讀取 yaml 文件,那么自然也能生成 yaml 文件。
import?yaml data?=?{ ????"girl":?[ ????????{"name":?"古明地覺",?"age":?17,?"place":?"東方地靈殿"}, ????????{"name":?"古明地戀",?"age":?16,?"place":?"東方地靈殿"}, ????????{"name":?"霧雨魔理沙",?"age":?16,?"place":?"魔法森林"} ????], ????"other":?{ ????????"古明地覺":?{"nickname":?["小五",?"少女覺",?"覺大人",?"小五蘿莉"], ?????????????????"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 文件長什么樣子。
我們來看 yml 文件,然后反推出相應的數(shù)據(jù)結構。首先整體是一個字典,里面有 girl 和 other 兩個 key。其中 girl 對應一個數(shù)組,數(shù)組里面每個元素都是字典,這是符合預期的。
然后 other 對應一個字典,而且這個字典內(nèi)部有三個鍵值對,key 分別是:古明地覺、古明地戀、霧雨魔理沙,各自對應的 value 又是一個字典(內(nèi)部有 length、nickname 兩個 key,length 對應整型、nickname 對應列表)。
最后再看一個本人之前項目中的 yml 文件,可以猜猜看解析出來長什么樣子。
解析一下看看和你想的是不是一樣的。
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'} ?????????????} } """
結果應該不難想,畢竟 yaml 文件不是很復雜。
以上就是Python實現(xiàn)解析yaml配置文件的示例詳解的詳細內(nèi)容,更多關于Python解析yaml配置文件的資料請關注腳本之家其它相關文章!
相關文章
可用于監(jiān)控 mysql Master Slave 狀態(tài)的python代碼
用于監(jiān)控MySQL Master Slave 狀態(tài)的python代碼,有需要的朋友可以參考下2013-02-02