1. 程式人生 > 程式設計 >python操作yaml說明

python操作yaml說明

1. 安裝PyYAML

pip install PyYAML

2. 載入yaml檔案

直接使用yaml.load()函式

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到yml檔案

使用yaml.safe_dump()函式

dump.py :

import yaml

d = {
 "kind": "Deployment","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 並解壓,在命令列下切換到解壓後的包目錄內並執行如下命令:

python setup.py install

如果想使用比純Python版本更快的LibYAML繫結,需要先下載並安裝LibYAML,然後在安裝PyYAML的時候執行如下命令:

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解析器和生成器之間有一些細微但並不真正重要的區別。

最常被問到的問題

為什麼如下所示的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}

關於這個問題,其實,儘管最後得到的YAML文件的樣式與原來的文件的樣式不一致,但是卻是正確的結果。

因為PyYAML預設會根據一個集合中是否有巢狀的集合來決定用哪種格式表示這個集合。如果一個集合中巢狀有其他集合,那麼會使用塊樣式來表示,否則會使用流樣式來表示。

如果想要集合總是以塊樣式表示,可以將 dump() 方法的 default_flow_style 引數值設為 False ,如下所示:

print(yaml.dump(yaml.load(document),default_flow_style=False))

上面程式碼的輸出為:

a: 1
b:
c: 3
d: 4

使用詳解

先匯入 yaml 模組:

import yaml

載入YAML

警告:呼叫 yaml.load 處理從不可信任的源接收的資料可能存在風險。yaml.load 與 pickle.load 的功能一樣強大,可以呼叫所有Python函式。

yaml.load 函式的作用是用來將YAML文件轉化成Python物件。如下所示:

>>> yaml.load("""
... - Hesperiidae
... - Papilionidae
... - Apatelodidae
... - Epiplemidae
... """)
['Hesperiidae','Papilionidae','Apatelodidae','Epiplemidae']

yaml.load 函式可以接受一個表示YAML文件的位元組字串、Unicode字串、開啟的二進位制檔案物件或者開啟的文字檔案物件作為引數。若引數為位元組字串或檔案,那麼它們必須使用 utf-8 、utf-16 或者 utf-16-le 編碼。yaml.load 會檢查位元組字串或者檔案物件的BOM(byte order mark)並依此來確定它們的編碼格式。如果沒有發現 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 函式將它們全部反序列化,得到的是一個包含所有反序列化後的YAML文件的生成器物件:

>>> documents = """
... name: bob
... age: 18
... ---
... name: alex
... age: 20
... ---
... name: jason
... age: 16
... """
>>> datas = yaml.load_all(documents)
>>> datas
<generator object load_all at 0x105682228>
>>> for data in datas:
...   print(data)
... 
{'name': 'bob','age': 18}
{'name': 'alex','age': 20}
{'name': 'jason','age': 16}

PyYAML允許使用者構造任何型別的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 類的例項,也可以使用標籤 !!python/object 來進行構建,如下所示:

>>> 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')

注意,如果從不信任的源(例如網際網路)接收一個YAML文件並由此構建一個任意的Python物件可能存在一定的風險。而使用 yaml.safe_load 方法能夠將這個行為限制為僅構造簡單的Python物件,如整數或者列表。

定義一個繼承自yaml.YAMLObject 類的子類,然後將這個子類的類屬性 yaml_loader 的值設定為 yaml.SafeLoader ,這樣,這個類的物件就被標記為是安全的,從而可以被 yaml.safe_load 方法識別。不過有一點需要注意,在反序列化這樣的Python物件時,只能使用 safe_load 和 safe_load_all 方法。

轉儲YAML

yaml.dump 函式接受一個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 可以接受第二個可選引數,用於寫入生成的YAML文字,這個引數的值可以是開啟的文字或者二進位制檔案物件。如果不提供這個可選引數,則直接返回生成的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 函式。該函式接受一個Python的列表或者生成器物件作為第一個引數,表示要序列化的多個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,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 方法還支援多個關鍵字引數,用來指定生成的YAML流中YAML文件的樣式和是否包含其他資訊。下面就來詳細介紹下每個引數的含義和用法。

stream

指定由於輸出YAML流的開啟的檔案物件。預設值為 None,表示作為函式的返回值返回。

default_flow_style

是否預設以流樣式顯示序列和對映。預設值為 None,表示對於不包含巢狀集合的YAML流使用流樣式。設定為 True 時,序列和對映使用塊樣式。

default_style

預設值為 None。表示標量不使用引號包裹。設定為 '"' 時,表示所有標量均以雙引號包裹。設定為 "'" 時,表示所有標量以單引號包裹。

canonical

是否以規範形式顯示YAML文件。預設值為 None,表示以其他關鍵字引數設定的值進行格式化,而不使用規範形式。設定為 True 時,將以規範形式顯示YAML文件中的內容。

indent

表示縮排級別。預設值為 None, 表示使用預設的縮排級別(兩個空格),可以設定為其他整數。

width

表示每行的最大寬度。預設值為 None,表示使用預設的寬度80。

allow_unicode

是否允許YAML流中出現unicode字元。預設值為 False,會對unicode字元進行轉義。設定為 True 時,YAML文件中將正常顯示unicode字元,不會進行轉義。

line_break

設定換行符。預設值為 None,表示換行符為 '',即空。可以設定為 \n、\r 或 \r\n。

encoding

使用指定的編碼對YAML流進行編碼,輸出為位元組字串。預設值為 None,表示不進行編碼,輸出為一般字串。

explicit_start

每個YAML文件是否包含顯式的指令結束標記。預設值為 None,表示流中只有一個YAML文件時不包含顯式的指令結束標記。設定為 True 時,YAML流中的所有YAML文件都包含一個顯式的指令結束標記。

explicit_end

每個YAML文件是否包含顯式的文件結束標記。預設值為 None,表示流中的YAML文件不包含顯式的文件結束標記。設定為 True 時,YAML流中的所有YAML文件都包含一個顯式的文件結束標記。

version

用於在YAML文件中指定YAML的版本號,預設值為 None,表示不在YAML中當中指定版本號。可以設定為一個包含兩個元素的元組或者列表,但是第一個元素必須為1,否則會引發異常。當前可用的YAML的版本號為1.0、1.1 和1.2。

tags

用於指定YAML文件中要包含的標籤。預設值為 None,表示不指定標籤指令。可以設定為一個包含標籤的字典,字典中的鍵值對對應各個不同的標籤名和值。

>>> data = {'code': 200,'status': 'success','message': [10,"Got it"]}
>>> print(yaml.dump(data,version=(1,2))) # 設定YAML版本
%YAML 1.2
---
code: 200
message: [10,true,Got it]
status: success

>>> print(yaml.dump(data,2),tags={'!name!': 'test'})) # 設定標籤指令
%YAML 1.2
%TAG !name! test
---
code: 200
message: [10,# 設定使用塊樣式
...         version=(1,...         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,# 設定標量使用單引號包裹
...         version=(1,...         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,# 設定標量使用雙引號包裹 
...         version=(1,...         default_style='"'))
%YAML 1.2
%TAG !name! test
---
"code": !!int "200"
"message":
- !!int "10"
- !!bool "true"
- "Got it"
"status": "success"

>>> print(yaml.dump(data,# 設定YAML文件包含顯式的指令結束標記和文件結束標記
...         explicit_start=True,...         explicit_end=True))
---
code: 200
message: [10,Got it]
status: success
...

>>> print(yaml.dump(data,canonical=True)) # 設定文件使用規範形式
---
!!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格式進行編碼
b'code: 200\nmessage: [10,Got it]\nstatus: success\n'
>>> user_info = {'name': '張學友','age': 57,'外號': ['歌神','烏蠅哥']}
>>> print(yaml.dump(user_info)) # 若不設定 allow_unicode 引數,則unicode字元會轉義
age: 57
name: "\u5F20\u5B66\u53CB"
"\u5916\u53F7": ["\u6B4C\u795E","\u4E4C\u8747\u54E5"]
 
>>> print(yaml.dump(user_info,allow_unicode=True)) # 設定允許包含unicode字元
age: 57
name: 張學友
外號: [歌神,烏蠅哥]

構造、表示和解析

可以定義自己的特定於應用程式的標記。最簡單的方法是定義 yaml.YAMLObject 的子類,如下所示:

>>> class Person(yaml.YAMLObject):
...   yaml_tag = '!Person'
...   def __init__(self,gender={self.gender!r})"
... 

如上的定義已經足夠自動化反序列化和序列化 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節點轉換為類例項的 constructors 和用來將YAML節點反序列化為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)

預設的 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 物件轉化成使用 !dict 標籤標記的標量節點的 *representers,然後註冊它,如下所示:

>> def dice_representer(dumper,data):
...   return dumper.represent_scalar('!dice','%sd%s' % data)
... 
>>> yaml.add_representer(Dice,dice_representer)

現在,序列化一個 Dice 物件的例項後的輸入就與期望的一樣了:

>>> yaml.add_representer(Dice,dice_representer)
>>> print(yaml.dump({'gold': Dice(10,6)}))
{gold: !dice '10d6'}

下面,我們再來實現一個將使用 !dice 標籤標記的標量節點轉化為 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 標籤,那麼可以使用 add_implicit_resolver 函式告訴PyYAML所有未標記的形如 XdY 的普通標量具有顯式標籤 !dice,如下所示:

>>> import re
>>> pattern = re.compile(r'^\d+d\d+$')
>>> yaml.add_implicit_resolver('!dice',pattern)

現在,在定義 Dice 物件的時候可以不使用標籤了,如下所示:

>>> print(yaml.dump({'treasure': Dice(10,20)}))
{treasure: 10d20}

>>> print(yaml.load('damage: 5d10'))
{'damage': Dice(5,10)}

當將一個物件標記為安全的時候,在反序列化這樣的物件時只能使用 safe_load 或 safe_load_all 方法,否則會報錯,如下所示:

>>> class Person(yaml.YAMLObject):
...   yaml_tag = '!Person'
...   yaml_loader = yaml.SafeLoader
...   def __init(self,gender):
...     self.name = name
...     self.age = age
...     self.gender = gender
...   def __repr__(self):
...     return f"Person(name={self.name!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 "<unicode string>",line 2,column 1:
  !Person
  ^
>>> yaml.safe_load(text) # 使用 safe_load 方法可以正常反序列化
Person(name='Bob',gender='Male')

YAML語法

這一部分將介紹最常見的YAML結構以及相應的Python物件。

文件

YAML流是零個或多個YAML文件的集合。空的YAML流不包含YAML文件。YAML文件間用文件開始標記 --- 進行分隔。YAML文件可以包含一個可選的文件結束標記 ... 。如果流中只有一個文件,那麼可以不使用文件開始標記。包含文件開始標記的文件可以稱為 顯式文件 ,不包含文件開始標記的文件可以稱為 隱式文件。

下面是一個隱式文件:

- Multimedia
- Internet
- Education

下面是一個顯式文件:

---
- Afterstep
- CTWM
- Oroborus
...

下面是一個包含多個文件的YAML流:

---
- Employee
- Manager
- CEO
- CTO
---
- Student
---
- C
- C# # YAML中使用‘#' 來表示註釋(‘#'前面要有一個空格)
- C++
- Cold Fusion

塊序列

在塊內容中,使用破折號(dash) - 後跟一個空格(Space)來表示序列中的項。

下面是一個包含塊序列的文件:

- id
- name
- age

上述文件表示的一個如下的Python物件:

['id','name','age']

塊序列是可以巢狀的:

-
- Python
- Ruby
- JavaScript
- PHP
-
- Unix
- Linux
- Windows

上述文件表示如下的Python物件:

[['Python','JavaScript','PHP'],['Unix','Linux','Windows']]

在巢狀的塊序列中,內層的序列可以直接從當前行開始而不必從新的一行開始,如下所示:

- - Python
- Ruby
- JavaScript
- PHP
- - Unix
- Linux
- Windows

塊序列中可以巢狀在塊對映之中,在這種情況下,塊序列不需要縮排,如下所示:

Programing Languages:
- Java
- Swift
- C++
- Go
Operation System:
- Unix
- Linux
- Windows
- OSX

上述文件表示如下的Python物件:

{'Programing Languages': ['Java','Swift','C++','Go'],'Operation System': ['Unix','Windows']}

塊對映

塊內容中,使用冒號 : 後跟一個空格來分隔對映中的鍵和值。

name: bob
age: 28
gender: Male

上述文件表示如下的Python物件:

{'name': 'bob','age': 28,'gender': 'Male'}

複雜的鍵使用問號 ? 後跟一個空格來表示,如下所示:

? !!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中列表和字典結構的語法很像,如下所示:

{ str: [15,17],con: [16,16],dex: [17,18],wis: [16,int: [10,13],chr: [5,8] }

上述文件表示如下的Python物件:

{'dex': [17,'int': [10,'chr': [5,8],'wis': [16,'str': [15,'con': [16,16]}

標量

YAML中的標量共有5中樣式,其中塊標量有兩種樣式:

文字樣式(literal style)

摺疊樣式(folded style)

流標量有三種樣式:

普通樣式(plain style)

單引號樣式(single-quoted style)

雙引號樣式(double-quoted style)

這五種樣式的示例如下:

plain: Hello World
single-quoted: '所有內容都會原樣輸出'
double-quoted: "需要用反斜槓轉移特殊字元"
literal: |
每一行
都會
包含換行符
中間的每一個空行

都會用換行符代替
folded: >
除過最後一行的
換行符
會保留
其他行末尾的換行符
都會使用一個空格代替
中間的空行

將會使用一個換行符代替

上述文件表示如下的Python物件:

{'plain': 'Hello World',
'single-quoted': '所有內容都會原樣輸出',
'double-quoted': '需要用反斜槓轉移特殊字元',
'literal': '每一行\n都會\n包含換行符\n中間的每一個空行\n\n都會用換行符代替\n',
'folded': '除過最後一行的 換行符 會保留 其他行末尾的換行符 都會使用一個空格代替 中間的空行\n將會使用一個換行符代替\n'}


每種樣式都有其特點。普通標量不使用指示符來表示其開始和結束,因此它是最受限制的樣式。普通標量自然適用於表示引數和屬性的名稱

使用單引號標量,可以表示不包含特殊字元的任何值。單引號標量不存在轉義,除非是一對相鄰的引號 '' 被單引號所替換”。

雙引號是最強大的樣式,也是惟一可以表示任何標量值的樣式。雙引號標量內的字元允許轉義。使用轉義序列 \x* 和 \u*** ,可以表達任何ASCII或Unicode字元。

塊標量樣式有兩種:文字樣式和摺疊樣式。文字樣式是最適合於大型文字塊(如原始碼)的樣式。摺疊樣式類似於文字樣式,但是兩個相鄰的非空行中間的換行符會被替換成一個空格從而變成一行。

別名

使用YAML可以表示任何類圖結構的物件。如果希望從文件的不同部分引用相同的物件,則需要使用錨和別名。

其中,錨用 & 表示,別名用 * 表示。下面的例子將會演示錨和別名的使用:

emp1: &A
 name: bob
 age: 28
 gender: Male
emp2: *A

上述文件表示如下的Python物件:

{'emp1': {'name': 'bob','gender': 'Male'},
'emp2': {'name': 'bob','gender': 'Male'}}

PyYAML現在已經支援遞迴物件,下面的文件表示一個Python的列表,這個列表的元素是這個列表自身。

&A [ *A ]

標籤

標籤用來標識節點的資料型別。標準的YAML標籤的定義可以參考該文件:

http://yaml.org/type/index.html

標籤可以是隱式地,如下所示:

boolen: true
integer: 3
float: 3.14

上述文件表示如下的Python物件:

{'boolean': True,'integer': 3,'float': 3.14}

標籤也可以是顯式的,如下所示:

boolean: !!bool "true"
integer: !!int "3"
float: !!float "3.14"

上述文件表示如下的Python物件:

{'boolean': True,'float': 3.14}

沒有顯式定義標籤的普通標量受制於隱式標籤解析。隱式標籤解析根據一組正則表示式檢查標量值,如果其中一個匹配,則為標量分配相應的標記。PyYAML允許應用程式新增自定義隱式標籤解析器。

YAML標籤和Python3 物件

YAML 標籤 Python物件
標準的YAML標籤
!!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的特殊標籤
!!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
複雜的Python標籤
!!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(...)的返回值

字串轉換

在Python3中,str 型別的物件將被轉變成使用標籤 !!str 標識的標量;bytes 型別的物件將被轉變成使用標籤 !!binary 標識的標量。為了考慮相容性,標籤 !!python/str 和 !!python/unicode 仍然可以使用,被其標識的標量將被轉變成 str 型別的物件。

名稱和模組

要表示靜態的Python物件,如函式和類,可以使用複雜的標籤Python !!python/name 。下面的例子演示瞭如何表示yaml模組中的dump方法:

!!python/name:yaml.dump

類似的,模組可以使用標籤 !!python/module :

!!python/module.yaml

物件

任何 pickleable 物件都可以使用標籤 !!python/object 來序列化:

!!python/object:module.Class { attribute: value,... }

為了支援 pickle 協議,PyYAML提供了兩個附加的標籤

!!python/object/new:module.Class 和 !!python/object/apply:module.function

這兩個標籤的使用方法如下:

!!python/object/new:module.Class
args: [argument,...]
kwds: {key: value,...}
stat: ...
listitems: [item,...]
dictitems: [key: value,...]

!!python/object/apply:module.function
args: [argument,...}
state: ...
listitems: [item,...]

以上這篇python操作yaml說明就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。