本篇內(nèi)容介紹了“python如何操作yaml方法講解”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
成都創(chuàng)新互聯(lián)是一家專注于成都做網(wǎng)站、網(wǎng)站設(shè)計與策劃設(shè)計,霞山網(wǎng)站建設(shè)哪家好?成都創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設(shè)10余年,網(wǎng)設(shè)計領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:霞山等地區(qū)。霞山做網(wǎng)站價格咨詢:189820811081. 安裝PyYAML
pip install PyYAML
2. 加載yaml文件
直接使用yaml.load()函數(shù)
demo.yml :
kind: Deployment apiVersion: apps/v1 metadata: name: podinfo namespace: yaml-demo spec: replicas: 1 selector: matchLabels: app: podinfo template: metadata: labels: app: podinfo spec: containers: - name: podinfod image: quay.io/stefanprodan/podinfo:0.3.0 ports: - containerPort: 9898
load.py :
import yaml import json result = yaml.load(open('demo.yml')) print json.dumps(result, indent=2)
輸出 :
{ "kind": "Deployment", "spec": { "replicas": 1, "template": { "spec": { "containers": [ { "image": "quay.io/stefanprodan/podinfo:0.3.0", "name": "podinfod", "ports": [ { "containerPort": 9898 } ] } ] }, "metadata": { "labels": { "app": "podinfo" } } }, "selector": { "matchLabels": { "app": "podinfo" } } }, "apiVersion": "apps/v1", "metadata": { "namespace": "yaml-demo", "name": "podinfo" } }
3. 持久化dict到y(tǒng)ml文件
使用yaml.safe_dump()函數(shù)
dump.py :
import yaml d = { "kind": "Deployment", "spec": { "replicas": 1, "template": { "spec": { "containers": [ { "image": "quay.io/stefanprodan/podinfo:0.3.0", "name": "podinfod", "ports": [ { "containerPort": 9898 } ] } ] }, "metadata": { "labels": { "app": "podinfo" } } }, "selector": { "matchLabels": { "app": "podinfo" } } }, "apiVersion": "apps/v1", "metadata": { "namespace": "yaml-demo", "name": "podinfo" } } result = yaml.safe_dump(d, encoding='utf-8', allow_unicode=True, default_flow_style=False) open('demo.yml', 'w').write(result)
demo.yml :
apiVersion: apps/v1 kind: Deployment metadata: name: podinfo namespace: yaml-demo spec: replicas: 1 selector: matchLabels: app: podinfo template: metadata: labels: app: podinfo spec: containers: - image: quay.io/stefanprodan/podinfo:0.3.0 name: podinfod ports: - containerPort: 9898
補充知識:Python的PyYAML模塊詳解
簡介
Python的PyYAML模塊是Python的YAML解析器和生成器。
安裝
簡單安裝
pip install pyyaml
從源碼安裝
下載源碼包PyYAML-3.13.tar.gz 并解壓,在命令行下切換到解壓后的包目錄內(nèi)并執(zhí)行如下命令:
python setup.py install
如果想使用比純Python版本更快的LibYAML綁定,需要先下載并安裝LibYAML,然后在安裝PyYAML的時候執(zhí)行如下命令:
python setup.py --with-libyaml install
為了使用基于LibYAML的解析器和生成器,請使用 CParser 和 CEmitter 類。例如:
from yaml import load, dump try: from yaml import Cloader as Loader, CDumper as Dumper except ImportError: from yaml import Loader, Dumper # ... data = load(stream, Loader=Loader) # ... output = dump(data, Dumper=Dumper)
請注意,基于純Python和基于LibYAML的YAML解析器和生成器之間有一些細(xì)微但并不真正重要的區(qū)別。
最常被問到的問題
為什么如下所示的YAML文檔在反序列化后再序列化,得到的YAML文檔的格式與原來不一樣?
import yaml document = """ a: 1 b: c: 3 d: 4 """ print(yaml.dump(yaml.load(document)))
其中,上面代碼的輸出為:
a: 1
b: {c: 3, d: 4}
關(guān)于這個問題,其實,盡管最后得到的YAML文檔的樣式與原來的文檔的樣式不一致,但是卻是正確的結(jié)果。
因為PyYAML默認(rèn)會根據(jù)一個集合中是否有嵌套的集合來決定用哪種格式表示這個集合。如果一個集合中嵌套有其他集合,那么會使用塊樣式來表示,否則會使用流樣式來表示。
如果想要集合總是以塊樣式表示,可以將 dump() 方法的 default_flow_style 參數(shù)值設(shè)為 False ,如下所示:
print(yaml.dump(yaml.load(document), default_flow_style=False))
上面代碼的輸出為:
a: 1
b:
c: 3
d: 4
使用詳解
先導(dǎo)入 yaml 模塊:
import yaml
加載YAML
警告:調(diào)用 yaml.load 處理從不可信任的源接收的數(shù)據(jù)可能存在風(fēng)險。yaml.load 與 pickle.load 的功能一樣強大,可以調(diào)用所有Python函數(shù)。
yaml.load 函數(shù)的作用是用來將YAML文檔轉(zhuǎn)化成Python對象。如下所示:
>>> yaml.load(""" ... - Hesperiidae ... - Papilionidae ... - Apatelodidae ... - Epiplemidae ... """) ['Hesperiidae', 'Papilionidae', 'Apatelodidae', 'Epiplemidae']
yaml.load 函數(shù)可以接受一個表示YAML文檔的字節(jié)字符串、Unicode字符串、打開的二進(jìn)制文件對象或者打開的文本文件對象作為參數(shù)。若參數(shù)為字節(jié)字符串或文件,那么它們必須使用 utf-8 、utf-16 或者 utf-16-le 編碼。yaml.load 會檢查字節(jié)字符串或者文件對象的BOM(byte order mark)并依此來確定它們的編碼格式。如果沒有發(fā)現(xiàn) BOM ,那么會假定他們使用 utf-8 格式的編碼。
yaml.load 方法的返回值為一個Python對象,如下所示:
>>> yaml.load("'hello': '?'") {'hello': '\uf8ff'} >>> with open('document.yaml', 'w') as f: ... f.writelines('- Python\n- Ruby\n- Java') ... >>> stream = open('document.yaml') >>> yaml.load(stream) ['Python', 'Ruby', 'Java']
如果字符串或者文件中包含多個YAML文檔,那么可以使用 yaml.load_all 函數(shù)將它們?nèi)糠葱蛄谢?,得到的是一個包含所有反序列化后的YAML文檔的生成器對象:
>>> documents = """ ... name: bob ... age: 18 ... --- ... name: alex ... age: 20 ... --- ... name: jason ... age: 16 ... """ >>> datas = yaml.load_all(documents) >>> datas>>> for data in datas: ... print(data) ... {'name': 'bob', 'age': 18} {'name': 'alex', 'age': 20} {'name': 'jason', 'age': 16}
PyYAML允許用戶構(gòu)造任何類型的Python對象,如下所示:
>>> document = """ ... none: [~, null] ... bool: [true, false, on, off] ... int: 55 ... float: 3.1415926 ... list: [Red, Blue, Green, Black] ... dict: {name: bob, age: 18} ... """ >>> yaml.load(document) {'none': [None, None], 'bool': [True, False, True, False], 'int': 55, 'float': 3.1415926, 'list': ['Red', 'Blue', 'Green', 'Black'], 'dict': {'name': 'bob', 'age': 18}}
即使是Python 類的實例,也可以使用標(biāo)簽 !!python/object 來進(jìn)行構(gòu)建,如下所示:
>>> class Person: ... def __init__(self, name, age, gender): ... self.name = name ... self.age = age ... self.gender = gender ... def __repr__(self): ... return f"{self.__class__.__name__}(name={self.name!r}, age={self.age!r}, gender={self.gender!r})" ... >>> yaml.load(""" ... !!python/object:__main__.Person ... name: Bob ... age: 18 ... gender: Male ... """) Person(name='Bob', age=18, gender='Male')
注意,如果從不信任的源(例如互聯(lián)網(wǎng))接收一個YAML文檔并由此構(gòu)建一個任意的Python對象可能存在一定的風(fēng)險。而使用 yaml.safe_load 方法能夠?qū)⑦@個行為限制為僅構(gòu)造簡單的Python對象,如整數(shù)或者列表。
定義一個繼承自yaml.YAMLObject 類的子類,然后將這個子類的類屬性 yaml_loader 的值設(shè)置為 yaml.SafeLoader ,這樣,這個類的對象就被標(biāo)記為是安全的,從而可以被 yaml.safe_load 方法識別。不過有一點需要注意,在反序列化這樣的Python對象時,只能使用 safe_load 和 safe_load_all 方法。
轉(zhuǎn)儲YAML
yaml.dump 函數(shù)接受一個Python對象并生成一個YAML文檔。
>>> import yaml >>> emp_info = { 'name': 'Lex', ... 'department': 'SQA', ... 'salary': 8000, ... 'annual leave entitlement': [5, 10] ... } >>> print(yaml.dump(emp_info)) annual leave entitlement: [5, 10] department: SQA name: Lex salary: 8000
yaml.dump 可以接受第二個可選參數(shù),用于寫入生成的YAML文本,這個參數(shù)的值可以是打開的文本或者二進(jìn)制文件對象。如果不提供這個可選參數(shù),則直接返回生成的YAML文檔。
>>> with open('document.yaml', 'w') as f: ... yaml.dump(emp_info, f) ... >>> import os >>> os.system('cat document.yaml') annual leave entitlement: [5, 10] department: SQA name: Lex salary: 8000 0
如果要將多個Python對象序列化到一個YAML流中,可以使用 yaml.dump_all 函數(shù)。該函數(shù)接受一個Python的列表或者生成器對象作為第一個參數(shù),表示要序列化的多個Python對象。
>>> obj = [{'name': 'bob', 'age': 19}, {'name': 20, 'age': 23}, {'name': 'leo', 'age': 25}] >>> print(yaml.dump_all(obj)) {age: 19, name: bob} --- {age: 23, name: 20} --- {age: 25, name: leo}
你甚至可以序列化一個Python類的實例,如下所示:
>>> class Person: ... def __init__(self, name, age, gender): ... self.name = name ... self.age = age ... self.gender = gender ... def __repr__(self): ... return f"{self.__class__.__name__}(name={self.name!r}, age={self.age!r}, gender={self.gender!r})" ... >>> print(yaml.dump(Person('Lucy', 26, 'Female'))) !!python/object:__main__.Person {age: 26, gender: Female, name: Lucy}
yaml.dump 和 yaml.dump_all 方法還支持多個關(guān)鍵字參數(shù),用來指定生成的YAML流中YAML文檔的樣式和是否包含其他信息。下面就來詳細(xì)介紹下每個參數(shù)的含義和用法。
stream
指定由于輸出YAML流的打開的文件對象。默認(rèn)值為 None,表示作為函數(shù)的返回值返回。
default_flow_style
是否默認(rèn)以流樣式顯示序列和映射。默認(rèn)值為 None,表示對于不包含嵌套集合的YAML流使用流樣式。設(shè)置為 True 時,序列和映射使用塊樣式。
default_style
默認(rèn)值為 None。表示標(biāo)量不使用引號包裹。設(shè)置為 '"' 時,表示所有標(biāo)量均以雙引號包裹。設(shè)置為 "'" 時,表示所有標(biāo)量以單引號包裹。
canonical
是否以規(guī)范形式顯示YAML文檔。默認(rèn)值為 None,表示以其他關(guān)鍵字參數(shù)設(shè)置的值進(jìn)行格式化,而不使用規(guī)范形式。設(shè)置為 True 時,將以規(guī)范形式顯示YAML文檔中的內(nèi)容。
indent
表示縮進(jìn)級別。默認(rèn)值為 None, 表示使用默認(rèn)的縮進(jìn)級別(兩個空格),可以設(shè)置為其他整數(shù)。
width
表示每行的大寬度。默認(rèn)值為 None,表示使用默認(rèn)的寬度80。
allow_unicode
是否允許YAML流中出現(xiàn)unicode字符。默認(rèn)值為 False,會對unicode字符進(jìn)行轉(zhuǎn)義。設(shè)置為 True 時,YAML文檔中將正常顯示unicode字符,不會進(jìn)行轉(zhuǎn)義。
line_break
設(shè)置換行符。默認(rèn)值為 None,表示換行符為 '',即空。可以設(shè)置為 \n、\r 或 \r\n。
encoding
使用指定的編碼對YAML流進(jìn)行編碼,輸出為字節(jié)字符串。默認(rèn)值為 None,表示不進(jìn)行編碼,輸出為一般字符串。
explicit_start
每個YAML文檔是否包含顯式的指令結(jié)束標(biāo)記。默認(rèn)值為 None,表示流中只有一個YAML文檔時不包含顯式的指令結(jié)束標(biāo)記。設(shè)置為 True 時,YAML流中的所有YAML文檔都包含一個顯式的指令結(jié)束標(biāo)記。
explicit_end
每個YAML文檔是否包含顯式的文檔結(jié)束標(biāo)記。默認(rèn)值為 None,表示流中的YAML文檔不包含顯式的文檔結(jié)束標(biāo)記。設(shè)置為 True 時,YAML流中的所有YAML文檔都包含一個顯式的文檔結(jié)束標(biāo)記。
version
用于在YAML文檔中指定YAML的版本號,默認(rèn)值為 None,表示不在YAML中當(dāng)中指定版本號??梢栽O(shè)置為一個包含兩個元素的元組或者列表,但是第一個元素必須為1,否則會引發(fā)異常。當(dāng)前可用的YAML的版本號為1.0、1.1 和1.2。
tags
用于指定YAML文檔中要包含的標(biāo)簽。默認(rèn)值為 None,表示不指定標(biāo)簽指令。可以設(shè)置為一個包含標(biāo)簽的字典,字典中的鍵值對對應(yīng)各個不同的標(biāo)簽名和值。
>>> data = {'code': 200, 'status': 'success', 'message': [10, True, "Got it"]} >>> print(yaml.dump(data, version=(1, 2))) # 設(shè)置YAML版本 %YAML 1.2 --- code: 200 message: [10, true, Got it] status: success >>> print(yaml.dump(data, version=(1, 2), tags={'!name!': 'test'})) # 設(shè)置標(biāo)簽指令 %YAML 1.2 %TAG !name! test --- code: 200 message: [10, true, Got it] status: success >>> print(yaml.dump(data, # 設(shè)置使用塊樣式 ... version=(1, 2), ... tags={'!name!': 'test'}, ... default_flow_style=False)) %YAML 1.2 %TAG !name! test --- code: 200 message: - 10 - true - Got it status: success >>> print(yaml.dump(data, # 設(shè)置標(biāo)量使用單引號包裹 ... version=(1, 2), ... tags={'!name!': 'test'}, ... default_flow_style=False, ... default_)) %YAML 1.2 %TAG !name! test --- 'code': !!int '200' 'message': - !!int '10' - !!bool 'true' - 'Got it' 'status': 'success' >>> print(yaml.dump(data, # 設(shè)置標(biāo)量使用雙引號包裹 ... version=(1, 2), ... tags={'!name!': 'test'}, ... default_flow_style=False, ... default_style='"')) %YAML 1.2 %TAG !name! test --- "code": !!int "200" "message": - !!int "10" - !!bool "true" - "Got it" "status": "success" >>> print(yaml.dump(data, # 設(shè)置YAML文檔包含顯式的指令結(jié)束標(biāo)記和文檔結(jié)束標(biāo)記 ... explicit_start=True, ... explicit_end=True)) --- code: 200 message: [10, true, Got it] status: success ... >>> print(yaml.dump(data, canonical=True)) # 設(shè)置文檔使用規(guī)范形式 --- !!map { ? !!str "code" : !!int "200", ? !!str "message" : !!seq [ !!int "10", !!bool "true", !!str "Got it", ], ? !!str "status" : !!str "success", } >>> print(yaml.dump(data, encoding='utf-8')) # 將YAML流使用utf-8格式進(jìn)行編碼 b'code: 200\nmessage: [10, true, Got it]\nstatus: success\n' >>> user_info = {'name': '張學(xué)友', 'age': 57, '外號': ['歌神', '烏蠅哥']} >>> print(yaml.dump(user_info)) # 若不設(shè)置 allow_unicode 參數(shù),則unicode字符會轉(zhuǎn)義 age: 57 name: "\u5F20\u5B66\u53CB" "\u5916\u53F7": ["\u6B4C\u795E", "\u4E4C\u8747\u54E5"] >>> print(yaml.dump(user_info, allow_unicode=True)) # 設(shè)置允許包含unicode字符 age: 57 name: 張學(xué)友 外號: [歌神, 烏蠅哥]
構(gòu)造、表示和解析
可以定義自己的特定于應(yīng)用程序的標(biāo)記。最簡單的方法是定義 yaml.YAMLObject 的子類,如下所示:
>>> class Person(yaml.YAMLObject): ... yaml_tag = '!Person' ... def __init__(self, name, age, gender): ... self.name = name ... self.age = age ... self.gender = gender ... def __repr__(self): ... return f"{self.__class__.__name__}(name={self.name!r}, age={self.age!r}, gender={self.gender!r})" ...
如上的定義已經(jīng)足夠自動化反序列化和序列化 Person 對象:
>>> text = """ ... --- !Person ... name: Bob ... age: 22 ... gender: Male ... """ >>> yaml.load(text) Person(name='Bob', age=22, gender='Male') >>> print(yaml.dump(Person('Bob', 22, 'Male'))) !Person {age: 22, gender: Male, name: Bob}
yaml.YAMLObject 使用元類魔法注冊了一個用來將YAML節(jié)點轉(zhuǎn)換為類實例的 constructors 和用來將YAML節(jié)點反序列化為Python類實例的表示器 representers。
如果你不想使用元類,你可以使用 yaml.add_constructor 和 yaml.add_representer 來注冊你的 constructors 和 representers。如下所示:
>>> class Dice(tuple): ... def __new__(cls, a, b): ... return tuple.__new__(cls, [a, b]) ... def __repr__(self): ... return 'Dice(%s, %s)' % self ... >>> print(Dice(3, 6)) Dice(3, 6)
默認(rèn)的 Dice 對象的表示看起來不太美觀:
>>> print(yaml.dump(Dice(3, 6))) !!python/object/new:__main__.Dice - !!python/tuple [3, 6]
假如你想要一個 Dice 對象序列化后表示成 AdB 這樣的形式,例如:
print(yaml.dump(Dict(3, 6))) # 期待輸出為:3d6
首先,需要定義一個用來將 Dict 對象轉(zhuǎn)化成使用 !dict 標(biāo)簽標(biāo)記的標(biāo)量節(jié)點的 *representers,然后注冊它,如下所示:
>> def dice_representer(dumper, data): ... return dumper.represent_scalar('!dice', '%sd%s' % data) ... >>> yaml.add_representer(Dice, dice_representer)
現(xiàn)在,序列化一個 Dice 對象的實例后的輸入就與期望的一樣了:
>>> yaml.add_representer(Dice, dice_representer) >>> print(yaml.dump({'gold': Dice(10, 6)})) {gold: !dice '10d6'}
下面,我們再來實現(xiàn)一個將使用 !dice 標(biāo)簽標(biāo)記的標(biāo)量節(jié)點轉(zhuǎn)化為 Dice 對象的 constructor 并注冊它:
>>> def dice_constructor(loader, node): ... value = loader.construct_scalar(node) ... a, b = map(int, value.split('d')) ... return Dice(a, b) ... >>> yaml.add_constructor('!dice', dice_constructor)
然后,你就可以加載一個 Dice 對象了:
>>> text = 'initial hit points: !dice 8d4' >>> print(yaml.load(text)) {'initial hit points': Dice(8, 4)}
如果你不想在任何地方都指定 !dice 標(biāo)簽,那么可以使用 add_implicit_resolver 函數(shù)告訴PyYAML所有未標(biāo)記的形如 XdY 的普通標(biāo)量具有顯式標(biāo)簽 !dice,如下所示:
>>> import re >>> pattern = re.compile(r'^\d+d\d+$') >>> yaml.add_implicit_resolver('!dice', pattern)
現(xiàn)在,在定義 Dice 對象的時候可以不使用標(biāo)簽了,如下所示:
>>> print(yaml.dump({'treasure': Dice(10, 20)})) {treasure: 10d20} >>> print(yaml.load('damage: 5d10')) {'damage': Dice(5, 10)}
當(dāng)將一個對象標(biāo)記為安全的時候,在反序列化這樣的對象時只能使用 safe_load 或 safe_load_all 方法,否則會報錯,如下所示:
>>> class Person(yaml.YAMLObject): ... yaml_tag = '!Person' ... yaml_loader = yaml.SafeLoader ... def __init(self, name, age, gender): ... self.name = name ... self.age = age ... self.gender = gender ... def __repr__(self): ... return f"Person(name={self.name!r}, age={self.age!r}, gender={self.gender!r})" ... >>> text = """ ... !Person ... name: Bob ... age: 22 ... gender: Male ... """ >>> yaml.load(text) # 不使用 safe_load 或 safe_load_all 方法會報錯 Traceback (most recent call last): ... yaml.constructor.ConstructorError: could not determine a constructor for the tag '!Person' in "", line 2, column 1: !Person ^ >>> yaml.safe_load(text) # 使用 safe_load 方法可以正常反序列化 Person(name='Bob', age=22, gender='Male')
YAML語法
這一部分將介紹最常見的YAML結(jié)構(gòu)以及相應(yīng)的Python對象。
文檔
YAML流是零個或多個YAML文檔的集合。空的YAML流不包含YAML文檔。YAML文檔間用文檔開始標(biāo)記 --- 進(jìn)行分隔。YAML文檔可以包含一個可選的文檔結(jié)束標(biāo)記 ... 。如果流中只有一個文檔,那么可以不使用文檔開始標(biāo)記。包含文檔開始標(biāo)記的文檔可以稱為 顯式文檔 ,不包含文檔開始標(biāo)記的文檔可以稱為 隱式文檔。
下面是一個隱式文檔:
- Multimedia
- Internet
- Education
下面是一個顯式文檔:
---
- Afterstep
- CTWM
- Oroborus
...
下面是一個包含多個文檔的YAML流:
---
- Employee
- Manager
- CEO
- CTO
---
- Student
---
- C
- C# # YAML中使用‘#' 來表示注釋(‘#'前面要有一個空格)
- C++
- Cold Fusion
塊序列
在塊內(nèi)容中,使用破折號(dash) - 后跟一個空格(Space)來表示序列中的項。
下面是一個包含塊序列的文檔:
- id
- name
- age
上述文檔表示的一個如下的Python對象:
['id', 'name', 'age']
塊序列是可以嵌套的:
-
- Python
- Ruby
- JavaScript
- PHP
-
- Unix
- Linux
- Windows
上述文檔表示如下的Python對象:
[['Python', 'Ruby', 'JavaScript', 'PHP'], ['Unix', 'Linux', 'Windows']]
在嵌套的塊序列中,內(nèi)層的序列可以直接從當(dāng)前行開始而不必從新的一行開始,如下所示:
- - Python
- Ruby
- JavaScript
- PHP
- - Unix
- Linux
- Windows
塊序列中可以嵌套在塊映射之中,在這種情況下,塊序列不需要縮進(jìn),如下所示:
Programing Languages:
- Java
- Swift
- C++
- Go
Operation System:
- Unix
- Linux
- Windows
- OSX
上述文檔表示如下的Python對象:
{'Programing Languages': ['Java', 'Swift', 'C++', 'Go'], 'Operation System': ['Unix', 'Linux', 'Windows']}
塊映射
塊內(nèi)容中,使用冒號 : 后跟一個空格來分隔映射中的鍵和值。
name: bob age: 28 gender: Male
上述文檔表示如下的Python對象:
{'name': 'bob', 'age': 28, 'gender': 'Male'}
復(fù)雜的鍵使用問號 ? 后跟一個空格來表示,如下所示:
? !!python/tuple [0, 0] : Start ? !!python/tuple [3, 5] : End
上述文檔表示如下的Python 對象:
{(0, 0): 'Start', (3, 5): 'End'}
塊映射是可以嵌套的,如下所示:
Employee: Job_title: Employee Salary: 5000 Annual Leave: 10 Manager: Job_title: Manager Salary: 8000 Annual Leave: 15
上述文檔表示如下的Python對象:
{'Employee': {'Job_title': 'Employee', 'Salary': 5000, 'Annual Leave': 10},
'Manager': {' Job_title': 'Manager', 'Salary': 8000, 'Annual Leave': 15}}
塊映射可以嵌套在塊序列中,如下所示:
- name: PyYAML
status: 4
license: MIT
language: Python
- name: PySyck
status: 5
license: BSD
language: Python
上述文檔表示如下的Python對象:
[{'name': 'PyYAML', 'status': 4, 'license': 'MIT', 'language': 'Python'},
{'name': 'PySyck', 'status': 5, 'license': 'BSD', 'language': 'Python'}]
流集合
YAML中流集合的語法與Python中列表和字典結(jié)構(gòu)的語法很像,如下所示:
{ str: [15, 17], con: [16, 16], dex: [17, 18], wis: [16, 16], int: [10, 13], chr: [5, 8] }
上述文檔表示如下的Python對象:
{'dex': [17, 18], 'int': [10, 13], 'chr': [5, 8], 'wis': [16, 16], 'str': [15, 17], 'con': [16, 16]}
標(biāo)量
YAML中的標(biāo)量共有5中樣式,其中塊標(biāo)量有兩種樣式:
文字樣式(literal style)
折疊樣式(folded style)
流標(biāo)量有三種樣式:
普通樣式(plain style)
單引號樣式(single-quoted style)
雙引號樣式(double-quoted style)
這五種樣式的示例如下:
plain: Hello World
single-quoted: '所有內(nèi)容都會原樣輸出'
double-quoted: "需要用反斜杠轉(zhuǎn)移特殊字符"
literal: |
每一行
都會
包含換行符
中間的每一個空行
都會用換行符代替
folded: >
除過最后一行的
換行符
會保留
其他行末尾的換行符
都會使用一個空格代替
中間的空行
將會使用一個換行符代替
上述文檔表示如下的Python對象:
{'plain': 'Hello World',
'single-quoted': '所有內(nèi)容都會原樣輸出',
'double-quoted': '需要用反斜杠轉(zhuǎn)移特殊字符',
'literal': '每一行\(zhòng)n都會\n包含換行符\n中間的每一個空行\(zhòng)n\n都會用換行符代替\n',
'folded': '除過最后一行的 換行符 會保留 其他行末尾的換行符 都會使用一個空格代替 中間的空行\(zhòng)n將會使用一個換行符代替\n'}
每種樣式都有其特點。普通標(biāo)量不使用指示符來表示其開始和結(jié)束,因此它是最受限制的樣式。普通標(biāo)量自然適用于表示參數(shù)和屬性的名稱
使用單引號標(biāo)量,可以表示不包含特殊字符的任何值。單引號標(biāo)量不存在轉(zhuǎn)義,除非是一對相鄰的引號 '' 被單引號所替換”。
雙引號是最強大的樣式,也是惟一可以表示任何標(biāo)量值的樣式。雙引號標(biāo)量內(nèi)的字符允許轉(zhuǎn)義。使用轉(zhuǎn)義序列 \x* 和 \u*** ,可以表達(dá)任何ASCII或Unicode字符。
塊標(biāo)量樣式有兩種:文字樣式和折疊樣式。文字樣式是最適合于大型文本塊(如源代碼)的樣式。折疊樣式類似于文字樣式,但是兩個相鄰的非空行中間的換行符會被替換成一個空格從而變成一行。
別名
使用YAML可以表示任何類圖結(jié)構(gòu)的對象。如果希望從文檔的不同部分引用相同的對象,則需要使用錨和別名。
其中,錨用 & 表示,別名用 * 表示。下面的例子將會演示錨和別名的使用:
emp1: &A name: bob age: 28 gender: Male emp2: *A
上述文檔表示如下的Python對象:
{'emp1': {'name': 'bob', 'age': 28, 'gender': 'Male'},
'emp2': {'name': 'bob', 'age': 28, 'gender': 'Male'}}
PyYAML現(xiàn)在已經(jīng)支持遞歸對象,下面的文檔表示一個Python的列表,這個列表的元素是這個列表自身。
&A [ *A ]
標(biāo)簽
標(biāo)簽用來標(biāo)識節(jié)點的數(shù)據(jù)類型。標(biāo)準(zhǔn)的YAML標(biāo)簽的定義可以參考該文檔:
http://yaml.org/type/index.html
標(biāo)簽可以是隱式地,如下所示:
boolen: true integer: 3 float: 3.14
上述文檔表示如下的Python對象:
{'boolean': True, 'integer': 3, 'float': 3.14}
標(biāo)簽也可以是顯式的,如下所示:
boolean: !!bool "true" integer: !!int "3" float: !!float "3.14"
上述文檔表示如下的Python對象:
{'boolean': True, 'integer': 3, 'float': 3.14}
沒有顯式定義標(biāo)簽的普通標(biāo)量受制于隱式標(biāo)簽解析。隱式標(biāo)簽解析根據(jù)一組正則表達(dá)式檢查標(biāo)量值,如果其中一個匹配,則為標(biāo)量分配相應(yīng)的標(biāo)記。PyYAML允許應(yīng)用程序添加自定義隱式標(biāo)簽解析器。
YAML標(biāo)簽和Python3 對象
YAML 標(biāo)簽 | Python對象 |
---|---|
標(biāo)準(zhǔn)的YAML標(biāo)簽 | |
!!null | None |
!!bool | bool |
!!int | int |
!!float | float |
!!binary | bytes |
!!timestamp | datetime.datetime |
!!omap, !!pairs | 元素為一個二元組的list |
!!set | set |
!!str | str |
!!seq | list |
!!map | dict |
Python的特殊標(biāo)簽 | |
!!python/none | None |
!!python/bool | bool |
!!python/bytes | bytes |
!!python/str | str |
!!python/unicode | str |
!!python/int | int |
!!python/long | int |
!!python/float | float |
!!python/complex | complex |
!!python/list | list |
!!python/tuple | tuple |
!!python/dict | dict |
復(fù)雜的Python標(biāo)簽 | |
!!python/name:module.name | module.name |
!!python/module:package.module | package.module |
!!python/object:module.cls | module.cls 的實例 |
!!python/object/new:module.cls | module.cls 的實例 |
!!python/object/apply:module.func | 方法 func(...)的返回值 |
字符串轉(zhuǎn)換
在Python3中,str 類型的對象將被轉(zhuǎn)變成使用標(biāo)簽 !!str 標(biāo)識的標(biāo)量;bytes 類型的對象將被轉(zhuǎn)變成使用標(biāo)簽 !!binary 標(biāo)識的標(biāo)量。為了考慮兼容性,標(biāo)簽 !!python/str 和 !!python/unicode 仍然可以使用,被其標(biāo)識的標(biāo)量將被轉(zhuǎn)變成 str 類型的對象。
名稱和模塊
要表示靜態(tài)的Python對象,如函數(shù)和類,可以使用復(fù)雜的標(biāo)簽Python !!python/name 。下面的例子演示了如何表示yaml模塊中的dump方法:
!!python/name:yaml.dump
類似的,模塊可以使用標(biāo)簽 !!python/module :
!!python/module.yaml
對象
任何 pickleable 對象都可以使用標(biāo)簽 !!python/object 來序列化:
!!python/object:module.Class { attribute: value, ... }
為了支持 pickle 協(xié)議,PyYAML提供了兩個附加的標(biāo)簽
!!python/object/new:module.Class 和 !!python/object/apply:module.function
這兩個標(biāo)簽的使用方法如下:
!!python/object/new:module.Class args: [argument, ...] kwds: {key: value, ...} stat: ... listitems: [item, ...] dictitems: [key: value, ...] !!python/object/apply:module.function args: [argument, ...] kwds: {key: value, ...} state: ... listitems: [item, ...] dictitems: [key: value, ...]
“python如何操作yaml方法講解”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!