Python实现解析yaml配置文件的示例详解

目录
  • 楔子
  • 字典
  • 数组
  • 标量
  • 引用
  • 生成 yaml 文件

楔子

前面我们介绍了 ini 格式的配置文件,本次来看看 yaml,它的表达能力相比 ini 更加的强大。yaml 文件以 .yml 结尾,在介绍它的语法结构之前我们先来看看 yaml 的一些基本规则。

  • 大小写敏感;
  • 使用缩进表示层级关系,并且缩进只能用空格、不可以使用 tab 键。缩进的空格数目不重要,只要相同层级的元素左侧对齐即可;
  • # 表示注释,# 到行尾的所有字符都会被忽略;

yaml 支持的数据结构有以下三种:

  • 字典:键值对的集合;
  • 数组:多个元素组成的集合;
  • 标量:单个、不可分割的值;

Python 解析 yaml 则是通过一个名为 pyyaml 的库,直接 pip install pyyaml 即可。

下面我们来介绍一下 yaml 的数据结构。

字典

类似于 Python 的字典,使用键值对表示:

name: satori
# 或者写成下面的形式
{name: satori}

Python 解析之后会是什么结果呢?

import yaml

config = """
name: satori
"""

# yaml.safe_load:只解析自己信任的输入
# yaml.unsafe_load:不检测输入的安全性
print(yaml.safe_load(config))
"""
{'name': 'satori'}
"""

config = """
{name: satori}
"""
print(yaml.safe_load(config))
"""
{'name': 'satori'}
"""

在 yaml 里面,字典的 value 也可以是一个字典:

info: {name: satori, address: 东方地灵殿}

Python 解析的结果如下:

import yaml

config = """
info: {name: satori, address: 东方地灵殿}
"""

print(yaml.safe_load(config))
"""
{
  'info': {'name': 'satori', 
           'address': '东方地灵殿'}
}
"""

还是很简单的。

数组

一组连字符开头的行,构成一个数组。

- 古明地觉
- 古明地恋
- 雾雨魔理沙
# - 后面要有空格
# 或者写成下面的形式
[古明地觉, 古明地恋, 雾雨魔理沙]

Python 解析的结果如下:

import yaml

config = """
- 古明地觉
- 古明地恋
- 雾雨魔理沙
"""

print(yaml.safe_load(config))
"""
['古明地觉', '古明地恋', '雾雨魔理沙']
"""

config = """
[古明地觉, 古明地恋, 雾雨魔理沙]
"""

print(yaml.safe_load(config))
"""
['古明地觉', '古明地恋', '雾雨魔理沙']
"""

并且数组的子成员也可以是一个数组:

-
 - 古明地觉
 - 古明地恋
 - 雾雨魔理沙

Python 解析的结果如下:

import yaml

config = """
-
  - 古明地觉
  - 古明地恋
  - 雾雨魔理沙
"""

print(yaml.safe_load(config))
"""
[['古明地觉', '古明地恋', '雾雨魔理沙']]
"""

# 更简洁的写法
config = """
- [古明地觉, 古明地恋, 雾雨魔理沙]
"""

print(yaml.safe_load(config))
"""
[['古明地觉', '古明地恋', '雾雨魔理沙']]
"""

显然数组也可以放在字典中:

# 缩进对应的空格数没有要求,但是必须一样
# 对于当前这个键值对而言也可以没有缩进
girl:
    - 古明地觉
    - 古明地恋
    - 雾雨魔理沙
# 或者下面这种形式
girl: [古明地觉, 古明地恋, 雾雨魔理沙]
# 或者下面这种形式
{girl: [古明地觉, 古明地恋, 雾雨魔理沙]}

Python 解析的结果如下:

import yaml

config = """
girl:
  - 古明地觉
  - 古明地恋
  - 雾雨魔理沙
"""

print(yaml.safe_load(config))
"""
{'girl': ['古明地觉', '古明地恋', '雾雨魔理沙']}
"""

# 注意:上面的 girl 对应的是数组
# 因为每个元素前面都有 -
# 但如果没有的话会发生什么?
config = """
girl:
    古明地觉
    古明地恋
    雾雨魔理沙
"""

print(yaml.safe_load(config))
"""
{'girl': '古明地觉 古明地恋 雾雨魔理沙'}
"""
# 我们看到整体相当于是一个字符串
# 类似于 html,之间用一个空格代替
# 因此如果内容比较长,我们可以写成多行
# 但是注意:每一行前面必须有空格

然后是一个稍微复杂的例子:

import yaml

config = """
girl:
    # 会对应一个数组
    - 古明地觉
    - 古明地恋
    - 雾雨魔理沙
    
place1:
    # 虽然不是数组,但是内部是字典的形式
    # 所以会对应一个含有三个键值对的字典
    古明地觉: 东方地灵殿
    古明地恋: 东方地灵殿
    雾雨魔理沙: 魔法森林

place2:
  # 是数组,数组里面每个元素是一个字典
  - 古明地觉: 东方地灵殿
  - 古明地恋: 东方地灵殿
  - 雾雨魔理沙: 魔法森林
"""

print(yaml.safe_load(config))
"""
{
    'girl': ['古明地觉', '古明地恋', '雾雨魔理沙'],
    'place1': {'古明地觉': '东方地灵殿', 
               '古明地恋': '东方地灵殿', 
               '雾雨魔理沙': '魔法森林'},
    'place2': [{'古明地觉': '东方地灵殿'}, 
               {'古明地恋': '东方地灵殿'}, 
               {'雾雨魔理沙': '魔法森林'}]
}
"""

place1 对应的是一个字典,place2 对应的是一个数组。

标量

标量属于最基本的、不可再分的值,比较简单,我们就全部都说了吧。

import yaml

config = """
int: 123
float: 3.14
bool:
    - true 
    - false
# 波浪号表示空    
NoneType: ~  
datetime: 2020-11-11 12:12:13

# 使用两个 ! 可以进行类型强转
# 不过几乎用不到 
cast:
    - !!str 123
    - !!str true  
"""

print(yaml.safe_load(config))
"""
{
    'int': 123, 'float': 3.14,
    'bool': [True, False], 'NoneType': None,
    'datetime': datetime.datetime(2020, 11, 11, 12, 12, 13), 
    'cast': ['123', 'true']
}
"""

这里可能有人已经发现了,就是字符串不需要加引号,但如果里面有特殊字符怎么办?所以 yaml 是支持使用引号括起来的。

import yaml

config = """
name1: 古明地觉      a x   $ #  !!        
name2: "古明地觉      a x   $ #  !!"        
name3: '古明地觉      a x   $ #  !!'   
"""

print(yaml.safe_load(config))
"""
{'name1': '古明地觉      a x   $', 
 'name2': '古明地觉      a x   $ #  !!', 
 'name3': '古明地觉      a x   $ #  !!'}
"""

对于 yaml 而言,字符串默认是从第一个不是空格的字符、匹配到最后一个不是空格的字符(如果遇到 # 直接停止)。因此如果 value 的前面或后面有空格的话,那么这些空格是不会显示的,或者当中有 #,那么 # 后面的内容也不会显示。

解决办法是使用单引号或双引号括起来,如果内部还有引号,那么需要输入两遍进行转义(如果内部的引号和外面括起来的引号相同的话)。

引用

对于 yaml 而言,还支持我们采用 & 和 * 进行引用,举个例子:

import yaml

config = """
# 多了一个 &db_info_ref
# 相当于起了个名字,叫 db_info_ref
db_info: &db_info_ref  
    host: 127.0.0.1
    port: 5432
    user: postgres
    password: 123456

deploy:
    os: Linux
    # 将内容直接扔到里面来  
    <<: *db_info_ref  
"""

print(yaml.safe_load(config))
"""
{
    'db_info': {'host': '127.0.0.1',
                'port': 5432,
                'user': 'postgres',
                'password': 123456},
    'deploy': {'host': '127.0.0.1',
               'port': 5432,
               'user': 'postgres',
               'password': 123456,
               'os': 'Linux'}
}
"""

& 用来建立锚点,<< 表示合并当前数据,* 表示用来引用锚点。还可以作用在数组中:

import yaml

config = """
- &name 古明地觉 
- 古明地恋
- 雾雨魔理沙
- *name
"""

print(yaml.safe_load(config))
"""
['古明地觉', '古明地恋', 
 '雾雨魔理沙', '古明地觉']
"""

生成 yaml 文件

既然能够读取 yaml 文件,那么自然也能生成 yaml 文件。

import yaml

data = {
    "girl": [
        {"name": "古明地觉", "age": 17, "place": "东方地灵殿"},
        {"name": "古明地恋", "age": 16, "place": "东方地灵殿"},
        {"name": "雾雨魔理沙", "age": 16, "place": "魔法森林"}
    ],
    "other": {
        "古明地觉": {"nickname": ["小五", "少女觉", "觉大人", "小五萝莉"],
                 "length": 155},
        "古明地恋": {"nickname": ["恋恋"], "length": 155},
        "雾雨魔理沙": {"nickname": ["摸你傻"], "length": 155}
    }
}

with open("cfg.yml", "w", encoding="utf-8") as f:
    yaml.dump(data, f, allow_unicode=True, indent=2)

然后我们看看生成的 yml 文件长什么样子。

我们来看 yml 文件,然后反推出相应的数据结构。首先整体是一个字典,里面有 girl 和 other 两个 key。其中 girl 对应一个数组,数组里面每个元素都是字典,这是符合预期的。

然后 other 对应一个字典,而且这个字典内部有三个键值对,key 分别是:古明地觉、古明地恋、雾雨魔理沙,各自对应的 value 又是一个字典(内部有 length、nickname 两个 key,length 对应整型、nickname 对应列表)。

最后再看一个本人之前项目中的 yml 文件,可以猜猜看解析出来长什么样子。

解析一下看看和你想的是不是一样的。

import yaml

with open(".gitlab-ci.yml", "r", encoding="utf-8") as f:
    data = f.read()

data = yaml.safe_load(data)
print(data)
"""
{
    'stages': ['test'], 
    'cache': {'key': '${CI_COMMIT_REF_SLUG}', 
              'paths': ['.cache/pip']},
    'variables': {'PIP_CACHE_DIR': '$CI_PROJECT_DIR/.cache/pip'},
    'test': {'stage': 'test', 
             'image': 'xxxxxxx/python:3.8.1-thanosclient-buster', 
             'only': ['branches', 'tags'],
             'services': ['mysql:5.7'],
             'variables': {'PROJECT': 'XXXXXX', 
                           'PIP_CACHE_DIR': '$CI_PROJECT_DIR/.cache/pip',
                           'MARKETING_CONFIG': 'config/room/ci.cn-gz.toml',
                           'MYSQL_DATABASE': 'activity', 
                           'MYSQL_ROOT_PASSWORD': 'password',
                           'MYSQL_INITDB_SKIP_TZINFO': '1'}
             }
}
"""

结果应该不难想,毕竟 yaml 文件不是很复杂。

以上就是Python实现解析yaml配置文件的示例详解的详细内容,更多关于Python解析yaml配置文件的资料请关注我们其它相关文章!

(0)

相关推荐

  • 使用 Python 解析配置文件格式

    第一步是选择配置文件的格式:INI.JSON.YAML 或 TOML. 有时,程序需要足够的参数,将它们全部作为命令行参数或环境变量既不让人愉快也不可行. 在这些情况下,你将需要使用配置文件. 有几种流行的配置文件格式.其中包括古老的(虽然有时定义不明确)INI 格式,虽然流行但有时难以手写的 JSON 格式,使用广泛但有时在细节方面令人意外的 YAML 格式,以及很多人还没有听说过的最新出现的 TOML. 你的首要任务是选择一种格式,然后记录该选择.解决了这个简单的部分之后就是时候解析配置了.

  • Python3操作YAML文件格式方法解析

    数据及配置文件之争 数据及文件通常有三种类型: 配置文件型:如ini,conf,properties文件,适合存储简单变量和配置项,最多支持两层,不适合存储多层嵌套数据 表格矩阵型:如csv,excel等,适合于存储大量同类数据,不适合存储层级结构的数据 多层嵌套型:如XML,HTMl,JSON.YAML,TOML等,适合存储单条或少数多层嵌套数据,不适合存储大量数据 YAML兼容JSON格式,简洁,强大,灵活,可以很方便的构造层级数据并快速转为Python中的字典. YAML简介 YAML(Y

  • python解析yaml文件过程详解

    YAML语法规则: http://www.ibm.com/developerworks/cn/xml/x-cn-yamlintro/ 下载PyYAML: http://www.yaml.org/ 解压安装: python setup.py install 1.新建test.yaml文件,内容如下: name: Tom Smith age: 37 spouse: name: Jane Smith age: 25 children: - name: Jimmy Smith age: 15 - nam

  • Python实现解析ini配置文件的示例详解

    目录 楔子 ini 文件 特殊格式 小结 楔子 在开发过程中,配置文件是少不了的,只不过我们有时会将 py 文件作为配置文件(config.py),然后在其它的模块中直接导入.这样做是一个好主意,不过配置文件是有专门的格式的,比如:ini, yaml, toml 等等. 而对于 Python 而言,也都有相应的库来解析相应格式的文件,下面我们来看看 ini 文件要如何解析. ini 文件 先来了解一下 ini 文件的格式: [satori] name = 古明地觉 age = 16 where 

  • Python基于yaml文件配置logging日志过程解析

    一.使用logging.config.dictConfig()函数读取配置信息,参数是字典类型 with open(file="./loggingconfigyaml.yaml", mode='r', encoding="utf-8")as file: logging_yaml = yaml.load(stream=file, Loader=yaml.FullLoader) # print(logging_yaml) # 配置logging日志:主要从文件中读取ha

  • Python实现解析yaml配置文件的示例详解

    目录 楔子 字典 数组 标量 引用 生成 yaml 文件 楔子 前面我们介绍了 ini 格式的配置文件,本次来看看 yaml,它的表达能力相比 ini 更加的强大.yaml 文件以 .yml 结尾,在介绍它的语法结构之前我们先来看看 yaml 的一些基本规则. 大小写敏感: 使用缩进表示层级关系,并且缩进只能用空格.不可以使用 tab 键.缩进的空格数目不重要,只要相同层级的元素左侧对齐即可: # 表示注释,# 到行尾的所有字符都会被忽略: yaml 支持的数据结构有以下三种: 字典:键值对的集

  • Python学习之yaml文件的读取详解

    目录 yaml 文件的应用场景与格式介绍 yaml 文件的应用场景 yaml 文件的格式 第三方包 - pyyaml 读取 yaml 文件的方法 yaml文件读取演示案例 yaml 文件的应用场景与格式介绍 yaml 文件的应用场景 yaml其实也类似于 json.txt ,它们都属于一种文本格式.在我们的实际工作中, yaml 文件经常作为服务期配置文件来使用. 比如一些定义好的内容,并且不会修改的信息,我们就可以通过定义 yaml 文件,然后通过读取这样的文件,将数据导入到我们的服务中进行使

  • Python实现邮件自动下载的示例详解

    开始码代码之前,我们先来了解一下三种邮件服务协议: 1.SMTP协议 SMTP(Simple Mail Transfer Protocol),即简单邮件传输协议.相当于中转站,将邮件发送到客户端. 2.POP3协议 POP3(Post Office Protocol 3),即邮局协议的第3个版本,是电子邮件的第一个离线协议标准.该协议把邮件下载到本地计算机,不与服务器同步,缺点是更易丢失邮件或多次下载相同的邮件. 3.IMAP协议 IMAP(Internet Mail Access Protoc

  • Python实现强制复制粘贴的示例详解

    目录 前因后果 流程思路 代码展示 效果展示 前因后果 公司有人阳了,今天在家上班,突然小姨子就问我有没有baidu文库会员,想下载点东西,我心想这还要会员?用Python不是分分钟的事情! 然后我非常自信的告诉她不用会员随便下载,结果她顺势想来我家,还问我她姐姐在不在家,趁我一个人在家过来想干嘛?本着男孩子一个人在家要好好保护自己的原则,于是我过段拒绝了她! 兄弟们我做的对吗? 咱们来开始今天的内容,咱们不仅要强制复制粘贴,还要自动保存到world文档,就问你刑不刑! 需要的模块 reques

  • python人工智能算法之决策树流程示例详解

    目录 决策树 总结 决策树 是一种将数据集通过分割成小的.易于处理的子集来进行分类或回归的算法.其中每个节点代表一个用于划分数据的特征,每个叶子节点代表一个类别或一个预测值.构建决策树时,算法会选择最好的特征进行分割数据,使每个子集中的数据尽可能的归属同一类或具有相似的特征.这个过程会不断重复,类似于Java中的递归,直到达到停止条件(例如叶子节点数目达到一个预设值),形成一棵完整的决策树.它适合于处理分类和回归任务.而在人工智能领域,决策树也是一种经典的算法,具有广泛的应用. 接下来简单介绍下

  • 对python 生成拼接xml报文的示例详解

    最近临时工作要生成xml报名,通过MQ接口发送.简单小程序. 自增长拼成xml报文 Test_001.py # encoding=utf-8 import time orderId = '' s1= "\n" # for ID in range(1,5): item1 = "<item>" + \ "<orderID>" + str(ID) + "</orderID>" + \ "

  • Python中bisect的用法及示例详解

    bisect是python内置模块,用于有序序列的插入和查找. 查找: bisect(array, item) 插入: insort(array,item) 查找 import bisect a = [1,4,6,8,12,15,20] position = bisect.bisect(a,13) print(position) # 用可变序列内置的insert方法插入 a.insert(position,13) print(a) 输出: 5 [1, 4, 6, 8, 12, 13, 15, 2

  • python实现三壶谜题的示例详解

    前言 有一个充满水的8品脱的水壶和两个空水壶(容积分别是5品脱和3品脱).通过将水壶完全倒满水和将水壶的水完全倒空这两种方式,在其中的一个水壶中得到4品脱的水. 一.算法思想 算法分析 采用的算法思想是将某个时刻水壶中水的数量看作一个状态,用一个长度为3的数组表示. 初始状态便为[8,0,0],再拓展他的下一结点的可能结构. 若下一结点的结构已经被拓展过了便放弃,若没有拓展过则加入拓展列表(open_list)中.然后递归上述操作. 直到拓展列表(open_list)为空或者找到目标为止. 思想

  • Python机器学习从ResNet到DenseNet示例详解

    目录 从ResNet到DenseNet 稠密块体 过渡层 DenseNet模型 训练模型 从ResNet到DenseNet 上图中,左边是ResNet,右边是DenseNet,它们在跨层上的主要区别是:使用相加和使用连结. 最后,将这些展开式结合到多层感知机中,再次减少特征的数量.实现起来非常简单:我们不需要添加术语,而是将它们连接起来.DenseNet这个名字由变量之间的"稠密连接"而得来,最后一层与之前的所有层紧密相连.稠密连接如下图所示: 稠密网络主要由2部分构成:稠密块(den

随机推荐