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中常见的数据类型:
- 标量类型:
- 字符串:可以直接书写,或者用引号包围。
- 布尔值:
true
、false
。 - 整数:如
42
、-7
。 - 浮点数:如
3.14
、-0.001
。 - NULL:可以用
null
、~
或不写任何内容来表示。 - 时间和日期:如
2001-12-15T02:59:43.1Z
。
- 序列类型:
- 列表(List):使用短横线
-
开头的行表示列表项。 - 元组(Tuple):在Python中,YAML的列表会被解析为元组,如果列表中的项用逗号分隔并且整个列表用小括号包围。
- 列表(List):使用短横线
- 映射类型:
- 字典(Dictionary):使用键值对表示,键和值之间用冒号
:
分隔。
- 字典(Dictionary):使用键值对表示,键和值之间用冒号
- 复合类型:
- 嵌套的映射和序列:可以创建复杂的嵌套结构,例如字典中包含列表,列表中包含字典等。
- 特殊类型:
- 二进制数据:可以使用Base64编码表示。
- 文本块:可以使用
|
或>
来表示多行文本。 - 引用:可以使用
&
和*
来创建和引用锚点。
- 自定义类型:
- YAML允许通过标签(Tag)定义自定义类型,但这些类型需要解析器支持。
以下是一些YAML数据类型的示例:
- YAML允许通过标签(Tag)定义自定义类型,但这些类型需要解析器支持。
# 字符串
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.yamlpip 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格式具有多种表示方式,但最常见的是如下几种:- 基本格式(不包含分隔符):
YYYYMMDD
:例如20230104
表示2023年1月4日。
- 扩展格式(包含分隔符):
YYYY-MM-DD
:例如2023-01-04
表示2023年1月4日。
- 包含时间的格式:
YYYY-MM-DDTHH:MM:SS
:例如2023-01-04T12:34:56
表示2023年1月4日12点34分56秒。YYYYMMDDTHHMMSS
:例如20230104T123456
也是有效的,但较少使用。
- 包含时区的格式:
YYYY-MM-DDTHH:MM:SS+HH:MM
或YYYY-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.date
或datetime.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表示。