yaml文件讀取load()、寫入dump()


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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM