• 揭秘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
    import pyyaml
    
    2.3 load与dump

    使用dump写入数据

    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文件中的数据

    age: 30
    city: New York
    name: John
    

    使用load读取数据

    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写入数据

    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读取数据

    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写入数据

    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文件中的数据,可以发现,文件内容中通过---来对数据进行分割,实现多文档

    age: 30
    city: New York
    name: John
    ---
    age: 25
    city: London
    name: Alice
    

    使用safe_load_all读取数据

    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'}
    

    改方式读取的数据,返回一个生成器,可以通过list直接生成一个列表结果

    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 工具类封装

    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 单个文档操作
    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文件中内容为

    - age: 18
      gender:name: 张三
    - age: 19
      gender:name: 李四
    
    3.2 多个文档操作
    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文件中内容为

    age: 18
    gender:name: 张三
    ---
    age: 19
    gender:name: 李四
    

    ✏ 总结

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

    💖 欢迎关注我的公众号

    在这里插入图片描述

  • 相关阅读:
    Zen of Python(python之禅)
    JWT安全问题
    vue下载Excel文件
    远程小组软件开发过程(1):流程
    JAVA高级——lambda
    php mb_strpos() 函数详解
    顶级赛事:第十届CCF大数据与计算智能大赛开赛
    我的创作纪念日
    MySQL的存储过程
    [Html5基础训练]animation的step使用方法
  • 原文地址:https://blog.csdn.net/powerbiubiu/article/details/139417989