【Python基础】yaml使用篇

python+yaml使用


Python中yaml文件的读写(使用PyYAML库)。最近在搭建自动化测试项目过程中经常遇到yaml文件的读写,在准备测试数据过程中,也经常需要将数据临时存储在yaml文件中,正所谓好记性不如烂笔头,为了方便后续使用,决定记下笔记。

一,YAML 简介

YAML,Yet Another Markup Language的简写,通常用来编写项目配置,也可用于数据存储,相比conf等配置文件要更简洁。

二,YAML 语法

+ 基本语法规则细则:

1、大小写敏感

2、使用缩进表示层级关系

3、相同层级的元素左侧对齐

4、键值对用冒号 “:” 结构表示,冒号与值之间需用空格分隔

5、数组前加有 “-” 符号,符号与值之间需用空格分隔

6、None值可用null 和 ~ 表示

7、多组数据之间使用3横杠—分割

8、# 表示注释,但不能在一段代码的行末尾加 #注释,否则会报错

注意:网上查找到各种博客都提到yaml缩进时不能使用tab键,但我在pycharm编辑器里实际使用时是可以使用tab键进行缩进的,读写时并没有报错!

YAML(YAML Ain’t Markup Language)支持多种数据类型,可以表示从简单的标量值到复杂的嵌套结构。以下是YAML中常见的数据类型:

  1. 标量类型
    • 字符串:可以直接书写,或者用引号包围。
    • 布尔值:truefalse
    • 整数:如 42-7
    • 浮点数:如 3.14-0.001
    • NULL:可以用 null~ 或不写任何内容来表示。
    • 时间和日期:如 2001-12-15T02:59:43.1Z
  2. 序列类型
    • 列表(List):使用短横线 - 开头的行表示列表项。
    • 元组(Tuple):在Python中,YAML的列表会被解析为元组,如果列表中的项用逗号分隔并且整个列表用小括号包围。
  3. 映射类型
    • 字典(Dictionary):使用键值对表示,键和值之间用冒号 : 分隔。
  4. 复合类型
    • 嵌套的映射和序列:可以创建复杂的嵌套结构,例如字典中包含列表,列表中包含字典等。
  5. 特殊类型
    • 二进制数据:可以使用Base64编码表示。
    • 文本块:可以使用 |> 来表示多行文本。
    • 引用:可以使用 &* 来创建和引用锚点。
  6. 自定义类型
    • YAML允许通过标签(Tag)定义自定义类型,但这些类型需要解析器支持。
      以下是一些YAML数据类型的示例:
# 字符串
name: "Alice"
# 布尔值
is_active: true
# 整数
age: 30
# 浮点数
pi: 3.14
# NULL
nullable: null
# 列表
fruits:
  - apple
  - banana
  - cherry
# 字典
person:
  name: Bob
  age: 25
# 嵌套结构
employees:
  - name: Carol
    department: Sales
    skills:
      - Negotiation
      - Persuasion
  - name: Dave
    department: IT
    skills:
      - Programming
      - Networking
# 多行文本
description: |
  This is a multi-line text block.
  It preserves newlines.

YAML的灵活性使其成为配置文件、数据交换和存储的理想格式。不过,具体的YAML解析器可能对某些类型的支持有所不同。

三,安装第三方yaml文件处理库PyYAML

python没有自带的处理yaml文件的库,需要下载第三方库PyYAML 或 ruamel.yaml
pip install pyyaml
# 下载速度慢的话加上清华镜像源
pip install pyyaml -i https://pypi.tuna.tsinghua.edu.cn/simple

四,读取yaml文件

1.从yaml中读取字典

yaml中的字典格式如下:
# yaml文件,文件名为yamlData
osVersion: 10
account:
  username: xiaoqq
  password: 123456
deviceName: null
appPackage: ~
bool1: True

读取字典代码:

import yaml
with open('./yamlData.yml', 'r', encoding='utf-8') as f:
    result = yaml.load(f.read(), Loader=yaml.FullLoader)
print(result, type(result))
print(result['os'], type(result['os']))
print(result['osVersion'], type(result['osVersion']))
print(result['account'], type(result['account']))
print(result['account']['username'])
print(result['deviceName'])
print(result['appPackage'])
print(result['bool1'], type(result['bool1']))

2.从yaml读取list

yaml中list格式:数据前加'-' 并使用空格与数据间隔开,如下:
# yaml文件名yamlData
 
- Android
- 10
- null
- ~
- True

读取list代码:

import yaml
with open('./yamlData.yml', 'r', encoding='utf-8') as f:
    result = yaml.load(f.read(), Loader=yaml.FullLoader)
print(result, type(result))

3.从yaml中读取元组

yaml中存储元组格式:yaml中使用!!对数据类型进行转换,yaml中tuple由list转换而来。如下:
# yaml文件名yamlData
 
!!python/tuple
- Android
- 10
- null
- ~
- True

读取元组代码:

import yaml
with open('./yamlData.yml', 'r', encoding='utf-8') as f:
    result = yaml.load(f.read(), Loader=yaml.FullLoader)
print(result, type(result))

4.从yaml中读取多组数据

当然可以。以下是一个示例,展示了如何从YAML文件中读取数据并将其转换为Python数据类型。我们将使用PyYAML库的load函数来读取YAML文件并转换为Python数据结构。
首先,确保你已经安装了PyYAML库:

pip install pyyaml

假设你有一个YAML文件data_types.yaml,内容如下:

string: "Hello, World!"
boolean: true
integer: 42
float: 3.14
none: null
list:
- 1
- 2
- 3
- 4
- 5
tuple: [1, 2, 3]  # 注意:YAML中没有元组类型,这里用列表代替
dictionary:
  key1: value1
  key2: value2
nested_structure:
  list_of_dicts:
  - name: Alice
    age: 30
  - name: Bob
    age: 25
  dict_of_lists:
    fruits:
    - apple
    - banana
    - cherry
    vegetables:
    - carrot
    - broccoli
    - asparagus
multi_line_string: |
  This is a multi-line string.
  It preserves newlines and formatting.

现在,可以使用以下Python代码来读取这个YAML文件并将其内容转换为Python数据结构:

import yaml
# 读取YAML文件
with open('data_types.yaml', 'r', encoding='utf-8') as file:
    data = yaml.load(file, Loader=yaml.FullLoader)
# 打印读取的数据
print(data)
# 你可以像操作普通的Python数据结构一样操作这些数据
# 例如,访问列表中的第一个元素
print(data['list'][0])
# 访问嵌套结构中的信息
print(data['nested_structure']['list_of_dicts'][0]['name'])
# 处理多行字符串
print(data['multi_line_string'])

在这个例子中,我们使用yaml.load()函数读取data_types.yaml文件的内容,并将其转换为Python数据结构。Loader=yaml.FullLoader参数用于指定使用安全的加载器,以防止潜在的安全问题。
执行上述代码后,你将看到打印出的Python数据结构,以及如何访问这些数据结构中的特定信息。
请注意,由于YAML本身不支持元组类型,我们在YAML文件中使用列表来代替。如果你需要将这些列表转换回元组,你可以在读取数据后进行额外的处理。

# 如果需要将列表转换为元组
data['tuple'] = tuple(data['tuple'])
print(data['tuple'])

这样,你就可以将YAML文件中的数据读取为Python数据类型,并进行相应的操作和处理。

5.从yaml中读取多行字符串

在YAML中,多行字符串可以通过几种方式表示,最常见的是使用管道符(`|`)或大于号(`>`)。这两种符号在YAML中表示多行字符串时有所不同:
  • |:保留字符串中的换行符。
  • >:折叠字符串中的换行符,将多个连续的空白行转换为一个空格。
    以下是一个示例,展示了如何在YAML中表示多行字符串:
# 使用管道符保留换行符
multi_line_preserve:
  |
  This is a multi-line string.
  It preserves newlines.
# 使用大于号折叠换行符
multi_line_fold:
  >
  This is another multi-line string.
  It folds newlines into spaces.

在Python中,处理YAML中的多行字符串非常简单,因为YAML解析器会自动将它们转换为普通的字符串,其中包含相应的换行符或空格。以下是如何使用Python处理上述YAML中的多行字符串:

import yaml
# YAML数据
yaml_data = """
# 使用管道符保留换行符
multi_line_preserve:
  |
  This is a multi-line string.
  It preserves newlines.
# 使用大于号折叠换行符
multi_line_fold:
  >
  This is another multi-line string.
  It folds newlines into spaces.
"""
# 加载YAML数据
data = yaml.load(yaml_data, Loader=yaml.FullLoader)
# 访问并打印多行字符串
print("Multi-line Preserve:")
print(data['multi_line_preserve'])
print("\nMulti-line Fold:")
print(data['multi_line_fold'])

输出将显示:

Multi-line Preserve:
This is a multi-line string.
It preserves newlines.
Multi-line Fold:
This is another multi-line string. It folds newlines into spaces.

在这个例子中,multi_line_preserve保留了字符串中的换行符,而multi_line_fold将多个连续的空白行转换为一个空格。
处理YAML中的多行字符串时,需要注意的是:

  • 当你从YAML文件中读取多行字符串时,它们会被转换为包含换行符的普通字符串。
  • 如果你需要将多行字符串写回YAML文件,确保使用正确的符号(|>)来保持原有的格式。
    使用Python的yaml模块,你可以轻松地读取和写入YAML中的多行字符串,而无需进行特殊的处理。

6.yaml中读取时间格式

YAML中日期的格式遵循ISO 8601标准,这是一种国际标准,用于表示日期和时间的格式。ISO 8601格式具有多种表示方式,但最常见的是如下几种:
  1. 基本格式(不包含分隔符):
    • YYYYMMDD:例如 20230104 表示2023年1月4日。
  2. 扩展格式(包含分隔符):
    • YYYY-MM-DD:例如 2023-01-04 表示2023年1月4日。
  3. 包含时间的格式
    • YYYY-MM-DDTHH:MM:SS:例如 2023-01-04T12:34:56 表示2023年1月4日12点34分56秒。
    • YYYYMMDDTHHMMSS:例如 20230104T123456 也是有效的,但较少使用。
  4. 包含时区的格式
    • YYYY-MM-DDTHH:MM:SS+HH:MMYYYY-MM-DDTHH:MM:SS-HH:MM:例如 2023-01-04T12:34:56+08:00 表示2023年1月4日12点34分56秒,时区为UTC+8。
      在YAML中,日期通常可以作为标量值直接表示,例如:
date: 2023-01-04
datetime: 2023-01-04T12:34:56+08:00

当使用Python的yaml模块解析YAML文件时,这些日期字符串通常会被解析为Python的datetime.datedatetime.datetime对象,具体取决于是否包含时间信息。
以下是一个Python示例,展示了如何解析YAML中的日期:

import yaml
from datetime import datetime
# YAML数据
yaml_data = """
date: 2023-01-04
datetime: 2023-01-04T12:34:56+08:00
"""
# 加载YAML数据
data = yaml.load(yaml_data, Loader=yaml.FullLoader)
# 访问并打印日期和时间
print("Date:", data['date'])  # 输出: Date: 2023-01-04
print("DateTime:", data['datetime'])  # 输出: DateTime: 2023-01-04 12:34:56+08:00

在这个例子中,date被解析为datetime.date对象,而datetime被解析为datetime.datetime对象。
需要注意的是,YAML解析器可能会根据其实现和配置来解析日期格式。一些解析器可能需要额外的配置来正确解析特定格式的日期。如果你使用的是PyYAML(Python的YAML模块),它通常可以很好地处理ISO 8601格式的日期。

7.自定义时间格式

在Python中,使用PyYAML库处理YAML文件时,默认的日期格式是ISO 8601。如果你需要自定义日期格式,可以通过以下几种方式实现:
1. 使用自定义构造器
你可以定义一个自定义的构造器来解析特定的日期格式。以下是一个示例,展示了如何解析一个非标准的日期格式(例如 `DD/MM/YYYY`):
import yaml
from datetime import datetime
# 自定义日期格式
date_format = "%d/%m/%Y"
# 自定义构造器
def construct_custom_date(loader, node):
    value = loader.construct_scalar(node)
    return datetime.strptime(value, date_format)
# 添加自定义构造器到PyYAML
yaml.add_constructor(u'!date', construct_custom_date)
# YAML数据,使用自定义标签 !date
yaml_data = """
date: !date 04/01/2023
"""
# 加载YAML数据
data = yaml.load(yaml_data, Loader=yaml.FullLoader)
# 访问并打印日期
print("Date:", data['date'])  # 输出: Date: 2023-01-04 00:00:00

在这个例子中,我们定义了一个名为 construct_custom_date 的函数,它使用 datetime.strptime 方法来解析日期字符串。我们使用 yaml.add_constructor 方法将这个函数注册为处理 !date 标签的构造器。

2. 使用自定义表示器
如果你想要在将Python对象序列化为YAML时使用自定义日期格式,可以定义一个自定义的表示器:
import yaml
from datetime import datetime
# 自定义日期格式
date_format = "%d/%m/%Y"
# 自定义表示器
def represent_custom_date(dumper, data):
    return dumper.represent_scalar(u'!date', data.strftime(date_format))
# 添加自定义表示器到PyYAML
yaml.add_representer(datetime, represent_custom_date)
# Python日期对象
date_obj = datetime(2023, 1, 4)
# 将日期对象序列化为YAML
yaml_data = yaml.dump({'date': date_obj}, default_flow_style=False)
# 打印YAML数据
print(yaml_data)

输出将类似于:

date: !date 04/01/2023

在这个例子中,我们定义了一个名为 represent_custom_date 的函数,它使用 strftime 方法将日期对象格式化为字符串。我们使用 yaml.add_representer 方法将这个函数注册为处理 datetime 对象的表示器。

3. 使用自定义标签
在上面的例子中,我们使用了自定义标签(例如 `!date`)来指示特定的日期格式。这是一种明确的方式,可以在YAML文档中清楚地表明使用了自定义格式。
注意事项
+ 当使用自定义构造器和表示器时,确保YAML文档的读者也知道这些自定义格式和标签。 + 自定义格式可能会影响YAML的互操作性,因为其他YAML解析器可能不识别你的自定义标签和格式。 + 在处理YAML文件时,始终考虑使用标准的ISO 8601日期格式,除非有充分的理由使用非标准格式。 通过这些方法,你可以在Python中使用PyYAML库自定义YAML的日期格式。

五,写入yaml文件

以下是一个示例,展示了如何将Python中的各种数据类型写入YAML文件。我们将使用PyYAML库的`dump`函数来将Python数据结构转换为YAML格式并写入文件。 首先,确保你已经安装了PyYAML库:
pip install pyyaml

然后,可以使用以下Python代码将不同的数据类型写入YAML文件:

import yaml
# 准备各种数据类型的示例
data = {
    'string': "Hello, World!",
    'boolean': True,
    'integer': 42,
    'float': 3.14,
    'none': None,
    'list': [1, 2, 3, 4, 5],
    'tuple': (1, 2, 3),  # 注意:元组会被转换为列表
    'dictionary': {
        'key1': 'value1',
        'key2': 'value2',
    },
    'nested_structure': {
        'list_of_dicts': [
            {'name': 'Alice', 'age': 30},
            {'name': 'Bob', 'age': 25},
        ],
        'dict_of_lists': {
            'fruits': ['apple', 'banana', 'cherry'],
            'vegetables': ['carrot', 'broccoli', 'asparagus'],
        },
    },
    'multi_line_string': """This is a multi-line string.
It preserves newlines and formatting."""
}
# 写入YAML文件
with open('data_types.yaml', 'w', encoding='utf-8') as file:
    yaml.dump(data, file, default_flow_style=False, allow_unicode=True)
print("Data has been written to data_types.yaml")

在这个例子中,我们创建了一个包含多种数据类型的字典data,然后使用yaml.dump()函数将这个字典写入到data_types.yaml文件中。default_flow_style=False参数用于指定YAML的输出格式为块格式(更易读),而allow_unicode=True参数允许在YAML文件中正确处理Unicode字符。
执行上述代码后,将会生成一个data_types.yaml文件,内容大致如下:

boolean: true
dictionary:
  key1: value1
  key2: value2
float: 3.14
integer: 42
list:
- 1
- 2
- 3
- 4
- 5
multi_line_string: |
  This is a multi-line string.
  It preserves newlines and formatting.
none: null
nested_structure:
  dict_of_lists:
    fruits:
    - apple
    - banana
    - cherry
    vegetables:
    - carrot
    - broccoli
    - asparagus
  list_of_dicts:
  - age: 30
    name: Alice
  - age: 25
    name: Bob
string: Hello, World!
tuple:
- 1
- 2
- 3

请注意,元组在YAML中表示为列表,因为YAML本身不支持元组类型。其他数据类型都按照预期转换成了相应的YAML表示。

### 关于 Spring Boot 项目整合 Spring Cloud 启动失败的问题 在 Spring Boot 和 Spring Cloud 的集成过程中,如果遇到 `Error creating bean` 或者类加载异常的情况,通常可能是由于以下几个原因引起的: #### 可能的原因分析 1. **版本兼容性问题** 如果使用的 Spring Boot 版本与 Spring Cloud 版本不匹配,则可能导致 Bean 创建失败或者类加载错误。确保所选的 Spring Boot 和 Spring Cloud 版本具有良好的兼容性[^1]。 2. **依赖冲突** 当引入多个依赖项时,可能会发生依赖冲突,尤其是当某些库的不同版本之间存在方法签名差异或类路径覆盖时。可以使用 Maven 提供的命令来检查依赖树并排除不必要的冲突: ```bash mvn dependency:tree ``` 3. **自定义配置类未被正确扫描到** 类 `[com.xuecheng.media.config.XxlJobConfig]` 被标记为无法通过 ClassLoader 加载,可能是因为该类所在的包不在组件扫描范围内。可以通过显式指定 `@ComponentScan` 注解或将该类移动至主应用程序所在包及其子包下解决问题。 4. **JDK 内部实现变化影响类加载机制** JDK 不同版本之间的内部实现可能存在细微差别,特别是对于一些非标准 API(如 `jdk.internal.loader.ClassLoaders$AppClassLoader`)。建议升级至最新稳定版 JDK 并重新测试应用运行情况。 5. **资源文件缺失或路径错误** 若 XXL-Job 配置涉及外部资源配置(例如 YAML 文件),需确认这些资源是否存在以及其访问路径是否正确设置。 --- #### 解决方案示例代码 以下是针对上述几种常见场景的具体解决方案: ##### 方法一:调整 Spring Boot 和 Spring Cloud 版本组合 修改项目的根 POM 文件中的 BOM 定义部分如下所示: ```xml <dependencyManagement> <dependencies> <!-- Spring Boot Starter Parent --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.0</version> <type>pom</type> <scope>import</scope> </dependency> <!-- Spring Cloud Dependency Management --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2021.0.3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> ``` ##### 方法二:排查依赖冲突 执行以下命令查看完整的依赖关系图谱,并移除冗余条目: ```bash mvn dependency:tree | grep spring-cloud-context ``` ##### 方法三:扩展组件扫描范围 假设当前主程序位于 `com.example.demo.Application` 下面,而目标配置类则处于独立模块中,则应在入口点增加额外声明: ```java @SpringBootApplication(scanBasePackages = {"com.example", "com.xuecheng"}) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` ##### 方法四:验证 JDK 兼容性和更新 尝试切换至更高版本的 OpenJDK 进行编译部署操作;同时注意清理旧缓存数据以防干扰正常流程。 --- ### 总结 综上所述,在处理此类问题时应优先考虑基础框架间的适配状况、潜在重复引用现象以及实际业务逻辑设计合理性等方面因素共同作用下的综合表现形式。只有逐一排除掉每一个可疑环节之后才能最终定位根本诱因并对症施治。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值