文章目录
- 一、读取yaml文件
- 1.1、读取单组数据
- 1.1.1、pyyaml
- 1.1.2、ruamel.yaml
- 1.2、读取多组数据
- 二、写入数据
- 2.1、写入单组数据
- 2.2、追加多组数据
- 附:`ruamel.yaml`和`PyYAML`区别
- 附:`yaml.safe_load()`和`yaml.load()`区别
YAML 是一种常见的标记性语言,常用于配置文件。本文就使用Python 对yaml文件的读写展开讨论。
yaml 语法请查看:https://blog.csdn.net/yuelai_217/article/details/130582142
一、读取yaml文件
1.1、读取单组数据
Python 读取yaml常见的有两种方式,一种是使用pyyaml
,另一种是ruamel.yaml
1.1.1、pyyaml
pip install pyyaml
test.yaml如下:
name: zhangsanage: 45
读取文件如下:
# coding=utf-8import yamldef read_yaml(file_path):with open(file_path, "r") as f:return yaml.safe_load(f)data = read_yaml("test.yaml")print(data)# {'age': 45, 'name': 'zhangsan'}
1.1.2、ruamel.yaml
pip install ruamel.yaml
同样解析test.yaml,如下:
from ruamel import yamlwith open("test.yaml") as f:config = yaml.load(f, Loader=yaml.RoundTripLoader)print config# ordereddict([('name', 'zhangsan'), ('age', 45)])print config["name"]
1.2、读取多组数据
修改test.yaml如下
name: zhangsanage: 45---name: lisiage: 25---name: wangwuage: 33
# coding=utf-8import yamldef read_yaml(file_path):with open(file_path, "r") as f:return yaml.safe_load_all(f.read())data = read_yaml("test.yaml")print(data)for d in data:print d# 结果如下<generator object load_all at 0x102d0c9b0>{'age': 45, 'name': 'zhangsan'}{'age': 25, 'name': 'lisi'}{'age': 33, 'name': 'wangwu'}
获取列表式结果
# coding=utf-8import yamldef read_yaml(file_path):with open(file_path, "r") as f:return list(yaml.safe_load_all(f.read()))data = read_yaml("test.yaml")print(data)# 结果如下[{'age': 45, 'name': 'zhangsan'}, {'age': 25, 'name': 'lisi'}, {'age': 33, 'name': 'wangwu'}]
使用ruamel.yaml
和PyYAML
在处理多组数据时结果一致
二、写入数据
2.1、写入单组数据
使用 safe_dump写入单组数据
# coding=utf-8import yamlimport osdef write_date_to_yaml(date):file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'test.yaml'))with open(file_path, 'w') as f:yaml.safe_dump(date, f, allow_unicode=True)info = {"name": "小红", "age": 18}write_date_to_yaml(info)# test.yaml 如下age: 18name: 小红# 文件被重写,原有内容丢失,修改'w'为'a',报错,因为没有插入多组数据分隔符name: zhangsanage: 45---name: lisiage: 25---name: wangwuage: 33age: 18# 缺少分隔符 ---name: 小红
2.2、追加多组数据
使用 safe_dump_all写入多组数据
import yaml# from ruamel import yamlimport osinfo = {"name": "小红", "age": 18}info1 = {"name": "小蓝", "age": 19}def write_date_to_yaml():file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'test.yaml'))with open(file_path, 'a') as f:yaml.safe_dump_all([info1, info], f, allow_unicode=True, default_flow_style=False)write_date_to_yaml()# 结果如下:age: 45name: zhangsan---age: 25name: lisi---age: 33name: wangwu # 此处没有分隔符,导致错误age: 19name: 小蓝---age: 18name: 小红
手动添加---
结果如下:
import yaml# from ruamel import yamlimport osinfo = {"name": "小红", "age": 18}info1 = {"name": "小蓝", "age": 19}def write_date_to_yaml():file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'test.yaml'))with open(file_path, 'a') as f:yaml.safe_dump_all(['---', info1, info], f, allow_unicode=True, default_flow_style=False)write_date_to_yaml()# 结果如下:age: 45name: zhangsan---age: 25name: lisi---age: 33name: wangwu'---' # 多出此行,是错误的---age: 19name: 小蓝---age: 18name: 小红
最终解决办法如下,采用先读取数据,修改数据后统一写入的办法,此处将读取的数据以列表形式展示,如果是单组数据,直接使用字典的update()
方法更新。
# coding=utf-8import yamlimport osinfo = {"name": "小红", "age": 18}info1 = {"name": "小蓝", "age": 19}def update_yaml():file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'test.yaml'))with open(file_path, 'r') as f:data = list(yaml.safe_load_all(f))data.append(info)data.append(info1)# data.update(info)with open(file_path, 'w') as fl:yaml.safe_dump_all(data, fl, encoding='utf-8')# sign = "---"update_yaml()# 结果如下age: 45name: zhangsan---age: 25name: lisi---age: 33name: wangwu---age: 18name: "\u5C0F\u7EA2"---age: 19name: "\u5C0F\u84DD"
汉字没有正常显示,需要使用中文unicode码写入allow_unicode=True
,修改为:
yaml.safe_dump_all(data, fl, allow_unicode=True)# 结果如下age: 45name: zhangsan---age: 25name: lisi---age: 33name: wangwu---age: 18name: 小红---age: 19name: 小蓝
附:ruamel.yaml
和PyYAML
区别
ruamel.yaml
和PyYAML
都是用于处理YAML格式的Python库,但它们之间有一些区别:
安装方式:ruamel.yaml可以通过pip直接安装,而PyYAML需要在安装前先安装C编译器。
YAML标准支持性:ruamel.yaml支持最新的YAML 1.2标准,而PyYAML只支持旧的YAML 1.1。
兼容性:ruamel.yaml与PyYAML的兼容性较低,因为它们使用不同的解析器和加载器,所以在某些情况下,ruamel.yaml不能正确地解析PyYAML生成的YAML文件。
性能:ruamel.yaml的解析速度要比PyYAML快,特别是在处理大型YAML文件时。
功能:ruamel.yaml提供了更多的功能,如可以保留注释、顺序等YAML文件的元数据信息,支持更多的Python数据类型和格式。
总的来说,如果需要处理较新的YAML标准或需要更高的性能和更多的功能,可以选择ruamel.yaml。如果只是简单地需求解析YAML文件,PyYAML是一个更简单的选择。
附:yaml.safe_load()
和yaml.load()
区别
在PyYAML库中,yaml.safe_load()和yaml.load()都可以用来解析YAML文件,但是有一些区别:
安全性:
yaml.safe_load()
可以安全地从YAML文档中加载数据,而不会执行任何可疑的Python代码。这使得它非常适合处理来自不受信任的源的YAML文档。yaml.load()
则不提供此安全功能,因此不建议使用它来加载未知或不受信任的YAML文档。数据类型:
yaml.safe_load()
只能加载基本的Python数据类型,例如字符串、数字、列表和字典等。而yaml.load()
可以加载任何Python对象,包括自定义类实例和Python内置类型的子类。执行Python代码:
yaml.load()
可以执行YAML文档中嵌入的Python代码。这使得它可以用于一些高级用例,例如将Python代码编译为YAML文档,并在不同的Python环境中加载它们。但是,由于安全风险,不建议在加载未知或不受信任的YAML文档时使用此功能。
因此,在处理未知或不受信任的YAML文档时,推荐使用yaml.safe_load()来保证安全性。
参考文档:
1、https://www.cnblogs.com/yxfeng/p/10396288.html
2、https://www.cnblogs.com/hhaostudy/p/16104098.html