Yaml介绍
1、介绍
YAML 是一种可读性非常高,与程序语言数据结构非常接近。同时具备丰富的表达能力和可扩展性,并且易于使用的数据标记语言。YAML全称其实是"YAML Ain't a Markup Language"(YAML不是一种标记语言)的递归缩写,所以它强调的是数据本身,而不是以标记为重点。
2、语法特点
大小写敏感
使用缩进表示层级关系,缩进不允许使用tab键,只允许使用空格
缩进的空格数不重要,只要相同层级元素左对齐即可
# 作为注释符号
3、支持的数据结构(类型)
对象:标示符:,键值对集合,又称映射(mapping)哈希(hash)字典(dict)
数组:标示符-,一组按照次序排列的值,又称序列
纯量:单个,不可再分的值,例如:
字符串:字符串一般默认不加双引号,当字符串包含了空格或者特殊字符等,可需要使用双引号
布尔值:true、True、false、False都可以
整数:如1、2、3,如用逗号或者空格分割,则会变成字符串传入
浮点数:如2.0
null:~ null和~都可以表示None
日期:如2023-03-20 格式:yyy-MM-dd
时间:如2023-03-20T20:20:20 格式:yyy-MM-dd HH:mm:ss,日期和时间可用T分割,也可用空格分割
PyYaml库介绍安装
PyYaml库是专门用来解析读取和写入的python库,pip安装命令如下:
pip install pyyaml
读取yaml文件
读取方法:yaml.load(yaml文件对象)
建议直接使用with来打开yaml文件对象,不需要再自己close关闭,代码如下:
import yaml
with open('xxx.yaml', 'r',encoding='utf-8') as f:
msg = yaml.load(f,Loader=yaml.FullLoader)
print(msg)
可以看到yaml.load函数里除了传入yaml文件对象,还传了Loader参数,这个是决定yaml文件的加载方式,有以下几种:
BaseLoader --仅加载最基本的YAML
SafeLoader --安全地加载YAML语言的子集。建议用于加载不受信任的输入
FullLoader --加载完整的YAML语言。避免任意代码执行,PyYAML5.1版本之后默认加载调用,但会出现warning
那么新建一个yaml文件,来读取试下
对象
对象的yaml文件内容如下:
#写法一: 对象键值对使用键:值冒号分割键值,特别注意,冒号后面(右边值前面)要有一个空格。
key1: value
#写法二:流式写法
key2: {k1: v1,k2: v2}
#写法三:缩进标识层级
key3:
name: 小明
age: 19
输出结果:
{'key1': 'value', 'key2': {'k1': 'v1', 'k2': 'v2'}, 'key3': {'name': '小明', 'age': 19}}
可以看到python解析对象打印出来也是以键值对形式的,yaml文件是用{}的字典格式,或者是左对齐层级的属性,在python里面解析出来都是字典格式
既然yaml是字典格式,python解析也是字典格式,那么如果是元组或者列表呢?
yaml文件:
#列表
key4: [1,2,3,4]
#元组
key5: (5,6,7,8)
输出结果:
'key4': [1, 2, 3, 4], 'key5': '(5,6,7,8)'
yaml中的列表,在python解析后仍旧是列表格式,但元组却在python解析后变成了字符串,这是需要注意的地方
数组
数组的yaml文件内容如下:
#以-开头的行标识构成一个数组,-也需要跟一个空格,不然会被识别成字符串
name:
- 小明
- 小红
- 小蓝
- {age: 19}
#数组中键值对存放
student:
-
id: 1
age: 13
-
id: 2
age: 18
需要注意:-标识符后也需要跟一个空格,不然会被识别成字符串
输出结果:
{'name': ['小明', '小红', '小蓝', {'age': 19}], 'student': [{'id': 1, 'age': 13}, {'id': 2, 'age': 18}]}
可以看到-标识后的元素,都会被当做一个列表中的元素
多维数组的yaml文件内容:
#多维数组
test:
-
- 1
- 2
-
- 3
- 4
输出结果:
{'test': [[1, 2], [3, 4]]}
纯量
纯量的yaml文件内容如下:
字符串: admin #字符串一般默认不加双引号,当字符串包含了空格或者特殊字符等,可需要使用双引号
字符串1: 'hi world@@!! 很棒'
布尔值: True #true、True、false、False都可以
整数: 1 #如用逗号或者空格分割,则会变成字符串传入
整数分割: 1,2,3,4
浮点数: 1.2
null: ~ #null和~ 都可以表示None
日期: 2023-03-20 #格式:yyy-MM-dd
时间: 2023-03-20T20:20:20 #格式: yyy-MM-dd HH:mm:ss,日期和时间可用T分割,也可用空格分割
时间分隔: 2023-03-20 20:20:20
输出结果:
{'字符串': 'admin', '字符串1': 'hi world@@!! 很棒', '布尔值': True, '整数': 1, '整数分割': '1,2,3,4', '浮点数': 1.2, None: None, '日期': datetime.date(2023, 3, 20), '时间': datetime.datetime(2023, 3, 20, 20, 20, 20), '时间分隔': datetime.datetime(2023, 3, 20, 20, 20, 20)}
可以看到日期和时间解析出来居然是datetime里的date和datetime的方法,这样看着很别扭,但是当你用for循环去取数据时,你会发现打印出来是yaml文件里的日期和时间格式
for循环解析yaml字典的python代码:
import yaml
with open('xxx.yaml', 'r',encoding='utf-8') as f:
msg = yaml.load(f,Loader=yaml.FullLoader)
print(msg)
for k in msg:
print(msg[k])
输出结果:
admin
hi world@@!! 很棒
True
1
1,2,3,4
1.2
None
2023-03-20
2023-03-20 20:20:20
2023-03-20 20:20:20
可以看到通过key取出来的value值,日期和时间格式仍是yaml中一样的格式
类型强转
YAML中可以使用两个感叹号,对数据类型进行强制转换,例如:
yaml文件:
#类型强转,YAML允许使用两个感叹号。强制转换数据类型
t1: !!str 123
t2: !!float '12'
t3: !!int '222'
输出结果:
{'t1': '123', 't2': 12.0, 't3': 222}
t1原本是整数int型,但被转换成了str字符串
t2原本是字符串,但被转换成了float浮点数
t3原来是字符串,但被转换成了int整数型
锚点使用
符号:&表示建立锚点,<<表示合并,*用来引用锚点
锚点就相当于一个模板,可以合并到其他数据当中,避免数据冗余
当需要合并的数据中有与锚点模板中的参数一致时,则是当前合并中数据的参数优先级更高,不会被锚点数据覆盖掉
锚点使用示例:
defaults: &defaults # 建立锚点defaults(相当于一个模板,可以合并到其他数据当中,避免数据冗余)
port: 3306
ip: 127.0.0.1
user: root
dev:
port: 3307
<<: *defaults # 将上述的数据合并到当前锚点的地方(<<表示合并到当前数据,但与锚点中的参数一致,则是当前数据的优先级比较高,不会被锚点数据覆盖,*用来引用锚点)
输出结果:
{'defaults': {'port': 3306, 'ip': '127.0.0.1', 'user': 'root'}, 'dev': {'port': 3307, 'ip': '127.0.0.1', 'user': 'root'}}
写入数据到yaml
写入方法:yaml.dump(dict)
allow_unicode=True:解决储存时unicode编码问题
代码如下:
import yaml
data = {
'school':'实验中学',
'Student':
{'name':'小明','age':18},
'Teacher':
{'name':'张三','age':39}
}
with open('student.yaml','w',encoding='utf-8') as f:
yaml.dump(data,f,allow_unicode=True)
yaml生成:
Student:
age: 18
name: 小明
Teacher:
age: 39
name: 张三
school: 实验中学
写入成功。但是写入的顺序是没有按照字典中的顺序写入,因为有个参数sort_keys,默认为True,表示字典中的键以A-z的顺序排序。所以要想按照实际顺序写入,将其设置为False即可
yaml.dump(data,f,allow_unicode=True,sort_keys=False)
输出结果如下:
school: 实验中学
Student:
name: 小明
age: 18
Teacher:
name: 张三
age: 39