Yaml文件介绍以及PyYAML库使用

Yaml文件介绍以及PyYAML库使用

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

💡 相关推荐

18磅等于多少斤
365即时比分足球

18磅等于多少斤

📅 07-03 👀 5821
密阳冰谷얼음골
365即时比分足球

密阳冰谷얼음골

📅 07-07 👀 3158
中国有多少家医院?
完美365体育app下载安装

中国有多少家医院?

📅 08-01 👀 9681