PyYaml簡單學習
阿新 • • 發佈:2020-12-19
YAML是一種輕型的配置檔案的語言,遠比JSON格式方便,方便人類讀寫,它通過縮排來表示結構,很具有Python風格。
安裝:pip insall pyyaml
YAML語法
- 文件
YAML資料流是0個或者多個文件,文件之間用---
分割,文件可選用...
結束,單個文件可用也可不用---
開頭。
隱式文件如下:
"""
- Multimedia
- Internet
- Education
"""
'\n- Multimedia\n- Internet\n- Education\n'
顯式文件如下:
""" --- - Multimedia - Internet - Education ... """
'\n---\n- Multimedia\n- Internet\n- Education\n...\n'
- 序列
序列用-空格
來表示
yaml.load("""
- The Dagger
- The daager
- The Daaage
""")
['The Dagger', 'The daager', 'The Daaage']
序列可以巢狀:
yaml.load("""
-
- HTML
- LaTex
- XML
- VRML
- YAML
-
- BSD
- GNU HURD
- LINUX
""")
[['HTML', 'LaTex', 'XML', 'VRML', 'YAML'], ['BSD', 'GNU HURD', 'LINUX']]
也可不用另起一行來新建巢狀的序列:
yaml.load("""
- 1.1
- - 2.1
- 2.2
- - - 3.1
- 3.2
- 3.3
""")
[1.1, [2.1, 2.2], [[3.1, 3.2, 3.3]]]
序列也可以巢狀到對映中:
yaml.load("""
left hand:
- Ring of Tesla
- Ring of King
right hand:
- Ring of Asia
- Ring of Cold
""")
{'left hand': ['Ring of Tesla', 'Ring of King'], 'right hand': ['Ring of Asia', 'Ring of Cold']}
- 對映
鍵值對用:空格
來表示:
yaml.load("""
base armor: 0
base damaage: [4,4]
plus to: 16
multi:
- test test
- tets
""")
{'base armor': 0,
'base damaage': [4, 4],
'plus to': 16,
'multi': ['test test', 'tets']}
複雜的鍵可以用?空格
,比如字典的鍵如果是tuple型別,而序列是List,眾所周知,Python中字典的鍵只能是不可變的物件,所以需要將List 轉換為tuple.
yaml.load("""
? !!python/tuple [0,0]
: The hero
""")
{(0, 0): 'The hero'}
對映也可以巢狀:
yaml.load("""
hero:
hp: 34
sp: 9
orc:
hp: 12
sp: 34
""")
{'hero': {'hp': 34, 'sp': 9}, 'orc': {'hp': 12, 'sp': 34}}
對映也可以巢狀在序列中
yaml.load("""
- name: PyYAML
status: 4
langauage: python
- name: PYSYCK
status: 5
license: BSD
""")
[{'name': 'PyYAML', 'status': 4, 'langauage': 'python'},
{'name': 'PYSYCK', 'status': 5, 'license': 'BSD'}]
- 標量
有5種標量:純文字,單引號,雙一號,字面量,摺疊式
yaml.load("""
plain: Scroll of Remove Curse
single-quoted: 'Easy know'
double-quoted: "?"
literal:
__ /.-.\
/ )_____________\\ Y
/_ /=== == === === =\ _\_
( /)=== == === === == Y \
`-------------------( o )
\___/
folded: >
It removed all ordinary curses from all equipped items. # 注意開頭的空格
Heavy or permanent curses are unaffected
""")
{'plain': 'Scroll of Remove Curse',
'single-quoted': 'Easy know',
'double-quoted': '?',
'literal': '__ /.-. / )_____________\\ Y /_ /=== == === === =\\ _\\_ ( /)=== == === === == Y `-------------------( o ) \\___/',
'folded': 'It removed all ordinary curses from all equipped items. # 注意開頭的空格 Heavy or permanent curses are unaffected \n'}
載入YAML
import yaml
直接用yaml.load
來載入一個不可信任的檔案是非常不安全的,yaml.load
跟pickle.load
一樣強大,都可以呼叫任何Python函式。可以考慮用yaml.safe_load
。
yaml.load
將一個YAML文件轉化為一個Python物件。
需要注意的是 '-' 與字串之間需要有空格,才表示一個列表。
a=yaml.load("""
- Hesper
- Pali
- Apat
- Epip
""")
a
['Hesper', 'Pali', 'Apat', 'Epip']
type(a)
list
yaml.load("""
測試: 中文
age: 30
""")
{'測試': '中文', 'age': 30}
需要重要的是 :
與字串之間也有空格
- 如果一個字串或者檔案包含多個文件,可以用
yaml.load_all
函式。
documents="""
---
name: first one
description: dkfsjk
---
name: johnyang
age: 29
---
- C
- C++
- C#
- B #
"""
注意多個文件之間用---
分割。
yaml.load_all(documents)
<generator object load_all at 0x0000029B36EC2390>
for data in yaml.load_all(documents):
print(data)
{'name': 'first one', 'description': 'dkfsjk'}
{'name': 'johnyang', 'age': 29}
['C', 'C++', 'C#', 'B']
空格 '#'
是表示註釋
- PyYAML允許構建任意型別的Python物件
yaml.load("""
none: [~,null]
bool: [ture,false,on,off]
int: 42
float: 3.14159
list: [LIST,RES]
dict: {hhp: 13,sps: dkf}
multiDict:
dksk: fjsdk
jfksd: eiw
""")
{'none': [None, None],
'bool': ['ture', False, True, False],
'int': 42,
'float': 3.14159,
'list': ['LIST', 'RES'],
'dict': {'hhp': 13, 'sps': 'dkf'},
'multiDict': {'dksk': 'fjsdk', 'jfksd': 'eiw'}}
- 甚至Python 類例項可以用
!!python/object
來建立
class Hero:
def __init__(self,name,hp,sp):
self.name=name
self.hp=hp
self.sp=sp
def __repr__(self):
return "%s(name=%r,hp=%r,sp=%r)" %(self.__class__.__name__,self.name,self.hp,self.sp)
yaml.load("""
!!python/object:__main__.Hero
name: jksdfk
hp: 1200
sp: 0
""")
Hero(name='jksdfk',hp=1200,sp=0)
注意 !!python/object:__main__.Hero
中的:
後面沒有空格!
匯出YAML
yaml.dump
接受Python物件,匯出為一個YAML文件。
print(yaml.dump({'name':'johnyang','age':29,'hobby':['coding','reading','thinking']}))
age: 29
hobby: [coding, reading, thinking]
name: johnyang
yaml.dump
接受第二個可選的引數,必須是開啟的文字/二進位制檔案,這種情況下,yaml.dump
將會把產生的yaml文件寫入該文字,否則yaml.dump
返回產生的文件。
stream=open('testYaml.yaml','w')
yaml.dump(data,stream)
print(yaml.dump(data))
{age: 29, name: johnyang}
print(yaml.dump([1,2,3],explicit_start=True))
--- [1, 2, 3]
print(yaml.dump(Hero('Gauss',hp=-3,sp=3)))
!!python/object:__main__.Hero {hp: -3, name: Gauss, sp: 3}
yaml.dump
支援管控輸出格式的可選引數
print(yaml.dump(list(range(50))))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
43, 44, 45, 46, 47, 48, 49]
print(yaml.dump(list(range(50)),width=50,indent=4))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49]
print(yaml.dump(list(range(5)),canonical=True)) #canonical 意思是典型的;規範化
---
!!seq [
!!int "0",
!!int "1",
!!int "2",
!!int "3",
!!int "4",
]
print(yaml.dump(list(range(5)),default_flow_style=False))
- 0
- 1
- 2
- 3
- 4
print(yaml.dump(list(range(5)),default_flow_style=True))
[0, 1, 2, 3, 4]
print(yaml.dump(list(range(5)),default_flow_style=True,default_style='""'))
[!!int "0", !!int "1", !!int "2", !!int "3", !!int "4"]