yaml簡介
1、yaml [ˈjæməl]: Yet Another Markup Language :另一種標記語言。yaml 是專門用來寫配置文件的語言,非常簡潔和強大。它實質上是一種通用的數據串行化格式。YAML 是一種非常靈活的格式,幾乎是 JSON 的超集。除了支持注釋、換行符分隔、多行字符串、裸字符串和更靈活的類型系統之外,YAML 也支持引用文件,以避免重復代碼。
2、在自動化測試中,通常使用yaml文件來編寫自動化測試用例。例如:
3、yaml基本語法規則:
- 大小寫敏感
- 使用縮進表示層級關系
- 縮進時不允許使用Tab鍵,只允許使用空格。
- 縮進的空格數目不重要,只要相同層級的元素左側對齊即可
- #表示注釋,從這個字符一直到行尾,都會被解析器忽略,這個和python的注釋一樣
4、yaml支持的數據結構有三種:
- 對象:鍵值對的集合,又稱為映射(mapping)/ 哈希(hashes) / 字典(dictionary)
- 數組:一組按次序排列的值,又稱為序列(sequence) / 列表(list)
- 純量(scalars):單個的、不可再分的值。字符串、布爾值、整數、浮點數、Null、時間、日期
5、python中,文件后綴名為.yml與.yaml的文件表示作用相同,即yaml文件;一般來說,最常用的使用.yml作為yaml文件后綴名。例如:

6、一個在線網站,用於校驗yaml文件格式是否正確: http://www.bejson.com/validators/yaml/
安裝yaml
使用pip安裝pyyaml模塊:
pip install pyyaml

yaml文件支持的數據結構舉例
1、yaml里面的鍵值對,也就是python里面的字典(dict)數據類型;比如python字典:
# python3.6 { "user": "admin", "psw": "123456, }
在yaml文件里可以這樣寫:
# yaml user: admin psw: 123456
2、字典嵌套字典:
# python3.6 "nb1": { "user": "admin", "psw": "123456, }
yaml文件里可以這樣寫:
# yaml nb1: user: admin psw: 123456
yaml文件中的序列(list)
yaml文件里面寫一個數組,需要在前面加一個‘-’符號。如下:
- admin1: 123456 - admin2: 111111 - admin3: 222222
對應python里面的list數據類型:
[{'admin1': 123456}],
[{'admin2': 111111}],
[{'admin3': 222222}]
注意:數字讀出來的是int或float類型
yaml文件中的純量(str)
1、int和float類型的數字
n1: 12.30
對應python中的
{'n1': 12.3}
2、布爾值用true和false表示
n2: true
n3: false
對應python中的
{'n2': True, 'n3': False}
注意:與從文本中讀出來的json格式的字符串通過反序列化轉為python數據類型相同。
3、None用~表示。
n4: ~
對應python中的
{'n4': None}
注意:從文本中讀取出來的json格式的字符串是null的時候轉換成python數據類型是None。
4、時間采用 ISO8601 格式
time1: 2001-12-14t21:59:43.10-05:00
對應python中的
{'time1': datetime.datetime(2001, 12, 15, 2, 59, 43, 100000)}
5、日期采用復合 iso8601 格式的年、月、日表示。
date1: 2017-07-31
對應python中的
{'date1': datetime.date(2017, 7, 31)}
6、使用兩個感嘆號,強制轉換數據類型。
# int轉str n6: !!str 123
對應python中的
{'n6': '123'}
# bool值轉str n7: !!str true
對應python中的
{'n7': 'true'}
舉例:在yaml文件寫入以下內容:
n1: 12.30 n2: true n3: false n4: ~ time1: 2018-04-18t21:59:43.10+08:00 date1: 2018-04-18 n6: !!str 123 n7: !!str true
python讀取結果:
{'n1': 12.3,
'n2': True,
'n3': False,
'n4': None,
'time1': datetime.datetime(2018, 4, 18, 13, 59, 43, 100000),
'date1': datetime.date(2018, 4, 18),
'n6': '123',
'n7': 'true'}
混合使用
1、list嵌套dict,在yaml里面寫入如下內容:
- user: admin1 psw: '123456' - user: admin2 psw: '111111' - user: admin3 psw: '222222'
用python讀取出來的結果:
[{'user': 'admin1', 'psw': '123456'},
{'user': 'admin2', 'psw': '111111'},
{'user': 'admin3', 'psw': '222222'}]
2、dict嵌套list,在yaml里面寫入如下內容:
nub1: - admin1 - '123456' nb2: - admin2 - '111111' nb3: - admin3 - '222222'
用python讀取出來的結果:
{'nub1': ['admin1', '123456'],
'nb2': ['admin2', '111111'],
'nb3': ['admin3', '222222']}
使用python的load()方法讀取yaml文件內容【反序列化】
data=yaml.load(f,Loader=yaml.FullLoader)
在 yaml.load 方法中, loader 參數有四種:
①BaseLoader:載入大部分的基礎YAML
②SafeLoader:載入YAML的子集,推薦在不可信的輸入時使用
③FullLoader:這是默認的載入方式,載入全部YAML
④UnsafeLoader:老版本的載入方式

注意:
需要加上參數: Loader=yaml.FullLoader
否則會報錯: YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/load for full details.
如圖:

舉例1:
import yaml def main(): with open("./data.yaml","r") as f: data=yaml.load(f,Loader=yaml.FullLoader) print(data) if __name__ == '__main__': main()
舉例2:
# coding:utf-8 import yaml import os # 獲取當前腳本所在文件夾路徑 curPath = os.path.dirname(os.path.realpath(__file__)) # 獲取yaml文件路徑 yamlPath = os.path.join(curPath, "cfgyaml.yaml") # open方法打開直接讀出來 f = open(yamlPath, 'r', encoding='utf-8') cfg = f.read() print(type(cfg)) # 讀出來是字符串 print(cfg) d = yaml.load(cfg,Loader=yaml.FullLoader) # 用load方法將json字符串轉換字典類型
print(d) print(type(d))
運行結果:

使用python的safe_load()方法讀取yaml文件內容【反序列化】
使用 yaml.safe_load() 方法,這個只解析基本的yaml標記,用來保證代碼的安全性,不過這對於平常保存數據是足夠了。
源碼如下:
def safe_load(stream): """ Parse the first YAML document in a stream and produce the corresponding Python object. Resolve only basic YAML tags. This is known to be safe for untrusted input. """ return load(stream, SafeLoader) def load(stream, Loader=None): """ Parse the first YAML document in a stream and produce the corresponding Python object. """ if Loader is None: load_warning('load') Loader = FullLoader loader = Loader(stream) try: return loader.get_single_data() finally: loader.dispose()
可以看到 safe_load() 方法就是在load方法中傳入SafeLoader的解析器,那么yaml有些什么Loader呢?
①UnsfeLoader & Loader The original Loader code that could be easily exploitable by untrusted data input. ②SafeLoader: Loads a subset of the YAML language, safely. This is recommended for loading untrusted input. 安全的加載yaml語言子集,對於加載不受信任的輸入,推薦使用此種方式 yaml.safe_load() ③FullLoader: Loads the full YAML language. Avoids arbitrary code execution. This is currently (PyYAML 5.1) the default loader called by yaml.load(input) (after issuing the warning). 加載完整的yaml語言,從上方的源碼可以看出這個是loade()默認的加載方式 ④BaseLoader: Only loads the most basic YAML 只加載最基本的yaml
safe_load()方法舉例:
a.yml文件:

代碼如下:
import yaml from string import Template def yaml_template(data: dict): with open("a.yml", encoding="utf-8") as f: re = Template(f.read()).substitute(data) return yaml.load(stream=re, Loader=yaml.FullLoader) if __name__ == '__main__': print(yaml_template({'token': 'hdadhh21uh1283hashdhuhh2hd', 'username': 'admin', 'password': '123456'}))
運行結果:
{'method': 'get', 'url': 'http://www.baidu.com', 'headers': {'Content-Type': 'application/json', 'token': 'hdadhh21uh1283hashdhuhh2hd'}, 'data': {'username': 'admin', 'password': 123456}}
使用python的dump()方法將python字典寫入yaml文件【序列化】
yaml.dump(data,f,encoding='utf-8',allow_unicode=True)
當data數據中有漢字時,加上: encoding='utf-8',allow_unicode=True
舉例:
import os import yaml yaml_dict = { "user": "general", "country": "China", "gender": "male", "address": "北京" } yaml_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'a.yml') with open(yaml_dir, 'w', encoding='utf-8', ) as f: yaml.dump(yaml_dict, f, encoding='utf-8', allow_unicode=True)
運行結果:

如果在寫入yaml文件不加 encoding='utf-8',allow_unicode=True 參數時,即:
import os import yaml yaml_dict = { "user": "general", "country": "China", "gender": "male", "address": "北京" } yaml_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'a.yml') with open(yaml_dir, 'w', encoding='utf-8', ) as f: yaml.dump(yaml_dict, f)
運行結果:

如上圖,如果在寫入yaml文件不加 encoding='utf-8',allow_unicode=True可以看到漢字是以unicode碼寫入到yaml文件當中。
在實際使用的時候可以配合,輸入參數更新配置文件中的參數使用:
def merge_config(config,args): for key_1 in config.keys(): if(isinstance(config[key_1],dict)): for key_2 in config[key_1].keys(): if(key_2) in dir(args): config[key_1][key_2] = getattr(args,key_2) return config config = yaml.load(open(args.config, 'r', encoding='utf-8'),Loader=yaml.FullLoader) config = merge_config(config,args)
