文章目录

    • 一、读取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.yamlPyYAML在处理多组数据时结果一致

二、写入数据

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.yamlPyYAML区别

ruamel.yamlPyYAML都是用于处理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