YAML 是一种常见的标记性语言,常用于配置文件。本文就使用Python 对yaml文件的读写展开讨论。
yaml 语法请查看:https://blog.csdn.net/yuelai_217/article/details/130582142
Python 读取yaml常见的有两种方式,一种是使用pyyaml
,另一种是ruamel.yaml
pip install pyyaml
test.yaml如下:
name: zhangsan
age: 45
读取文件如下:
# coding=utf-8
import yaml
def 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'}
pip install ruamel.yaml
同样解析test.yaml,如下:
from ruamel import yaml
with open("test.yaml") as f:
config = yaml.load(f, Loader=yaml.RoundTripLoader)
print config # ordereddict([('name', 'zhangsan'), ('age', 45)])
print config["name"]
修改test.yaml如下
name: zhangsan
age: 45
---
name: lisi
age: 25
---
name: wangwu
age: 33
# coding=utf-8
import yaml
def 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-8
import yaml
def 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
在处理多组数据时结果一致
使用 safe_dump写入单组数据
# coding=utf-8
import yaml
import os
def 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: 18
name: 小红
# 文件被重写,原有内容丢失,修改'w'为'a',报错,因为没有插入多组数据分隔符
name: zhangsan
age: 45
---
name: lisi
age: 25
---
name: wangwu
age: 33
age: 18 # 缺少分隔符 ---
name: 小红
使用 safe_dump_all写入多组数据
import yaml
# from ruamel import yaml
import os
info = {"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: 45
name: zhangsan
---
age: 25
name: lisi
---
age: 33
name: wangwu
# 此处没有分隔符,导致错误
age: 19
name: 小蓝
---
age: 18
name: 小红
手动添加---
结果如下:
import yaml
# from ruamel import yaml
import os
info = {"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: 45
name: zhangsan
---
age: 25
name: lisi
---
age: 33
name: wangwu
'---' # 多出此行,是错误的
---
age: 19
name: 小蓝
---
age: 18
name: 小红
最终解决办法如下,采用先读取数据,修改数据后统一写入的办法,此处将读取的数据以列表形式展示,如果是单组数据,直接使用字典的update()
方法更新。
# coding=utf-8
import yaml
import os
info = {"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: 45
name: zhangsan
---
age: 25
name: lisi
---
age: 33
name: wangwu
---
age: 18
name: "\u5C0F\u7EA2"
---
age: 19
name: "\u5C0F\u84DD"
汉字没有正常显示,需要使用中文unicode码写入allow_unicode=True
,修改为:
yaml.safe_dump_all(data, fl, allow_unicode=True)
# 结果如下
age: 45
name: zhangsan
---
age: 25
name: lisi
---
age: 33
name: wangwu
---
age: 18
name: 小红
---
age: 19
name: 小蓝
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