YAML是一种轻型的配置文件的语言,远比JSON格式方便,方便人类读写,它通过缩进来表示结构,很具有Python风格。
安装:pip insall pyyaml
YAML语法
- 文档
YAML数据流是0个或者多个文档,文档之间用---
分割,文档可选用...
结束,单个文档可用也可不用---
开头。
隐式文档如下:
"""
- Multimedia
- Internet
- Education
"""
'
- Multimedia
- Internet
- Education
'
显式文档如下:
"""
---
- Multimedia
- Internet
- Education
...
"""
'
---
- Multimedia
- Internet
- Education
...
'
- 序列
序列用-空格
来表示
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
'}
加载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"]