揭秘YAML:Python中的PyYAML应用

🍀 前言

博客地址:

👋 简介

本章节介绍YAML文件格式的操作,通过Python的第三方库 PyYaml 来实现文件操作,在 Pyhon 代码中无论读取还是写入,都是使用列表字典的数据类型,这种类型在使用起来很方便。

📖 正文

1 安装PyYaml

pip install pyyaml -i [https://pypi.tuna.tsinghua.edu.cn/simple](https://pypi.tuna.tsinghua.edu.cn/simple)

2 使用PyYaml

2.1 方法介绍

从Yaml文件中获取数据:

  • yaml.load(stream, Loader=yaml.Loader):用于从 YAML 字符串或文件中加载单个文档,使用默认的 Loader,它具有一些可能存在安全风险的功能,不推荐在不受信任的输入中使用;
  • yaml.safe_load(stream):提供更安全的加载,防止潜在的代码注入攻击,使用 SafeLoader 代替 Loader,推荐在处理不受信任的输入时使用;
  • yaml.safe_load_all(stream):类似于 safe_load,但是可以用于加载多个文档,它返回一个迭代器,允许逐个迭代加载多个文档;

将数据下如Yaml文件中:

  • yaml.dump(data, stream=None, Dumper=yaml.Dumper):用于将数据转储为 YAML 格式,默认使用 Dumper,它具有一些可能存在安全风险的功能,不推荐在不受信任的环境中使用;
  • yaml.safe_dump(data, stream=None):提供更安全的转储,防止潜在的代码注入攻击,使用 SafeDumper 代替 Dumper,推荐在处理不受信任的数据时使用;
  • yaml.safe_dump_all(documents, stream=None):类似于 safe_dump,但是用于转储多个文档,接受一个迭代器或可迭代对象,用于逐个转储多个文档。
2.2 导入pyyaml
python 复制代码
import pyyaml
2.3 load与dump

使用dump写入数据

python 复制代码
data = {'name': 'John', 'age': 30, 'city': 'New York'}
with open('test.yaml', 'w', encoding='utf-8') as file:
    yaml.dump(data, file, allow_unicode=True)

test.yaml文件中的数据

yaml 复制代码
age: 30
city: New York
name: John

使用load读取数据

python 复制代码
with open('test.yaml', 'r', encoding='utf-8') as file:
    data = yaml.load(file, Loader=yaml.Loader)
print(data)

# {'age': 30, 'city': 'New York', 'name': 'John'}

返回的数据为字典

2.4 safe_load与safe_dump

本小节的方法与2.3中的方法使用一样,唯一的区别在于2.3的方法存在风险,所以在不明确是否存在风险的情况,统一使用以下方法

使用safe_dump写入数据

python 复制代码
data = {'name': 'John', 'age': 30, 'city': 'New York'}
with open('test.yaml', 'w', encoding='utf-8') as file:
    yaml.safe_dump(data, file, allow_unicode=True)

使用safe_load读取数据

python 复制代码
with open('data.yaml', 'r', encoding='utf-8') as file:
    data = yaml.safe_load(file)

# {'age': 30, 'city': 'New York', 'name': 'John'}
2.5 safe_load_all与safe_dump_all

读取多个文档

使用safe_dump_all写入数据

python 复制代码
documents = [
    {'name': 'John', 'age': 30, 'city': 'New York'},
    {'name': 'Alice', 'age': 25, 'city': 'London'}
]
with open('multi_output.yaml', 'w', encoding='utf-8') as file:
    yaml.safe_dump_all(documents, file, allow_unicode=True)

test.yaml文件中的数据,可以发现,文件内容中通过---来对数据进行分割,实现多文档

yaml 复制代码
age: 30
city: New York
name: John
---
age: 25
city: London
name: Alice

使用safe_load_all读取数据

python 复制代码
with open('test.yaml', 'r', encoding='utf-8') as file:
    documents = yaml.safe_load_all(file)
    for doc in documents:
        print(doc)
        
# {'age': 30, 'city': 'New York', 'name': 'John'}
# {'age': 25, 'city': 'London', 'name': 'Alice'}

改方式读取的数据,返回一个生成器<generator object load_all at 0x0000025516EA8C10>,可以通过list直接生成一个列表结果

python 复制代码
with open('test.yaml', 'r', encoding='utf-8') as file:
    documents = yaml.safe_load_all(file)
    print(list(documents))
    
# [{'age': 30, 'city': 'New York', 'name': 'John'}, {'age': 25, 'city': 'London', 'name': 'Alice'}]

3 工具类封装

python 复制代码
import yaml
from typing import Union, List, Any, Dict


class YamlReader:

    def __init__(self, yaml_path: str, more: bool = False):
        """
        初始化
        :param yaml_path: 文件
        :param more: yaml文件内容模式,是否为多文档,默认为False
        """
        # 初始化判断yaml文件是否存在
        if os.path.exists(yaml_path):
            self.yaml_path = yaml_path
        else:
            with open(yaml_path, 'w', encoding='utf-8') as f:
                pass
        self.__more = more

    def read(self) -> Union[Dict[str, Any], List[Dict[str, Any]]]:
        """
        读取数据
        :return:
        """
        try:
            with open(self.yaml_path, 'r+', encoding='utf-8') as f:
                if self.__more:
                    data = list(yaml.safe_load_all(f))
                else:
                    data = yaml.safe_load(f)
            return data
        except Exception as e:
            print("读取失败,请检查读取yaml文件内容模式是否正确")

    def write(self, item: List[Dict[str, Any]]) -> None:
        """
        写入数据
        :param item: 写入数据
        :return:
        """
        with open(self.yaml_path, 'w+', encoding='utf-8') as f:
            if self.__more:
                yaml.safe_dump_all(item, f, allow_unicode=True)
            else:
                yaml.safe_dump(item, f, allow_unicode=True)

    def append(self, item: List[Dict[str, Any]]) -> None:
        """
        写入数据,追加写入
        :param item: 写入数据
        :return:
        """
        with open(self.yaml_path, 'a+', encoding='utf-8') as f:
            if self.__more:
                yaml.safe_dump_all(item, f, allow_unicode=True)
            else:
                yaml.safe_dump(item, f, allow_unicode=True)
3.1 单个文档操作
python 复制代码
if __name__ == '__main__':
    yr = YamlReader('test.yaml')
    data = [{'name': '张三', 'age': 18, 'gender': '男'}, {'name': '李四', 'age': 19, 'gender': '女'}]
    # 写入数据
    yr.write(data)
    # 读取数据
    print(yr.read())

# [{'age': 18, 'gender': '男', 'name': '张三'}, {'age': 19, 'gender': '女', 'name': '李四'}]

test.yaml文件中内容为

yaml 复制代码
- age: 18
  gender: 男
  name: 张三
- age: 19
  gender: 女
  name: 李四
3.2 多个文档操作
python 复制代码
if __name__ == '__main__':
    yr = YamlReader('test.yaml', more=True)
    data = [{'name': '张三', 'age': 18, 'gender': '男'}, {'name': '李四', 'age': 19, 'gender': '女'}]
    # 写入数据
    yr.write(data)
    # 读取数据
    print(yr.read())

    # [{'age': 18, 'gender': '男', 'name': '张三'}, {'age': 19, 'gender': '女', 'name': '李四'}]

test.yaml文件中内容为

yaml 复制代码
age: 18
gender: 男
name: 张三
---
age: 19
gender: 女
name: 李四

✏ 总结

通过 PyYaml 库操作 YAML 文件,可以灵活的实现数据的读取和写入,使用 PyYAML 实现 YAML 和 Python 对象的相互转换,但需要注意的是,YAML 文件对字母大小写敏感,同时需要注意缩进和空格。

💖 欢迎关注我的公众号

相关推荐
PieroPc3 分钟前
Python tkinter写的《电脑装配单》和 Html版 可打印 可导出 excel 文件
python·html·电脑
Cachel wood8 分钟前
Django REST framework (DRF)中的api_view和APIView权限控制
javascript·vue.js·后端·python·ui·django·前端框架
云计算DevOps-韩老师13 分钟前
【网络云计算】2024第52周-每日【2024/12/25】小测-理论&实操-自己构造场景,写5个系统管理的脚本-解析
开发语言·网络·云计算·bash·perl
暮色尽染16 分钟前
Python 正则表达式
开发语言·python
IT猿手18 分钟前
最新高性能多目标优化算法:多目标麋鹿优化算法(MOEHO)求解GLSMOP1-GLSMOP9及工程应用---盘式制动器设计,提供完整MATLAB代码
开发语言·算法·机器学习·matlab·强化学习
小爬虫程序猿20 分钟前
利用Java爬虫获取速卖通(AliExpress)商品详情的详细指南
java·开发语言·爬虫
幽络源小助理25 分钟前
Python使用requests_html库爬取掌阅书籍(附完整源码及使用说明)
python·html·python爬虫·爬虫教程·requests_html·爬取书籍·掌阅
取个名字真难呐27 分钟前
LossMaskMatrix损失函数掩码矩阵
python·深度学习·矩阵
南宫理的日知录28 分钟前
「Python数据科学」标量、向量、矩阵、张量与多维数组的辨析
python·numpy·数据科学
xlsw_29 分钟前
java全栈day21--Web后端实战之利用Mybaits查询数据
java·开发语言