在 Python 编程中,使用配置文件存储程序设置和选项是一种常见的做法。YAML 是一种人类友好的配置文件格式, 而 PyYAML 则是 Python 中用于处理 YAML 格式的库。现在一起了解这个库的用法。
YAML(不是 YAML 标记语言)是一种人类可读的数据序列化语言。 它通常用于配置文件, 但也用于数据存储(例如调试输出)或传输(例如文档标题)。
YAML 本机支持三种基本数据类型:标量(例如字符串,整数和浮点数),列表和关联数组。
官方推荐的 YAML 文件扩展名是 .yaml
。 Python 中有两个用于 YAML 的模块:PyYAML 和 ruamel.yaml
。
在本教程中使用前者。
读取 YAML 文件
假设有一个名为 config.yaml
的 YAML 配置文件。
配置文件示例:
with open('xx_config.yaml', 'w') as fo:
fo.write('''
server:
host: localhost
port: 8080
database:
type: MySQL
host: 127.0.0.1
port: 3306
username: root
password: password
logging:
level: info
file: app.log
''')
可以使用 safe_load()
来读取这个配置文件
safe_load(stream)
: 从文件或字符串中加载 YAML 数据。
一旦解析了一个 YAML 文件,就可以通过键来访问其内容。
import yaml
with open('xx_config.yaml', 'r',encoding="utf-8") as f:
config = yaml.safe_load(f)
host = config['server']['host']
port = config['server']['port']
print(f"地址: {host}, 端口: {port}")
地址: localhost, 端口: 8080
import yaml
config = {
'settings': {
'username': 'root',
'password': '123456'
}
}
with open('xx_new_config.yaml', 'w') as f:
yaml.safe_dump(config, f)
with open('xx_cfg2.yaml', 'w') as fo:
fo.write('''\
fruits:
- apple
- banana
- cherry
veggies:
- carrot: red
- broccoli: green
- spinach: green
''')
代码读取如下:
import yaml
with open('xx_cfg2.yaml', 'r') as file:
content = file.read()
data = yaml.safe_load(content)
fruits = data['fruits']
veggies = data['veggies']
print(f"Fruits: {fruits}")
Fruits: ['apple', 'banana', 'cherry']
print(f"Veggies: {veggies}")
Veggies: [{'carrot': 'red'}, {'broccoli': 'green'}, {'spinach': 'green'}]
实际应用场景
- 配置文件管理:YAML格式简单易读,非常适合作为配置文件。PyYAML可以轻松地将YAML文件解析为Python对象,方便程序读取和解析。
- 数据序列化和反序列化:PyYAML可以将Python对象序列化为YAML格式的字符串,也可以将YAML格式的字符串反序列化为Python对象。这使得PyYAML可以用于数据的交换和存储。
- 日志记录:使用PyYAML,可以将日志记录配置信息保存在YAML文件中,便于配置和修改。
- 自动化脚本:PyYAML可以用于自动化脚本中,通过YAML文件传递参数和配置信息,简化脚本的编写和配置。
- 测试数据生成:使用PyYAML可以生成符合特定要求的测试数据,便于测试程序的运行和验证。
- 数据迁移和转换:PyYAML可以用于数据的迁移和转换,将数据从一种格式转换为另一种格式,方便数据的处理和使用。
注意事项
- 大小写敏感:YAML是区分大小写的,因此需要注意键值对中的大小写是否正确。
- 缩进规则:YAML使用缩进来表示层级关系,缩进时需要使用空格,而不是制表符。并且,缩进的空格数量不重要,只要相同层级的元素左侧对齐即可。
- 注释格式:在YAML中,注释使用#表示,解析器会忽略这个字符。
- 数据类型转换:PyYAML会将YAML中的字符串值转换为相应的Python数据类型。例如,YAML中的数字会被转换为Python的整数或浮点数,布尔值会被转换为Python的True或False。
- 特殊字符处理:如果YAML字符串中包含特殊字符,如引号或冒号,需要进行转义处理。
- 异常处理:在使用PyYAML解析YAML文件时,需要注意异常处理。例如,如果YAML文件格式不正确,PyYAML会抛出异常。
- 依赖管理:PyYAML依赖于其他库,如libyaml。在使用PyYAML之前,需要确保这些依赖库已经正确安装。
- 安全性:在使用PyYAML加载用户提供的数据时,需要注意安全性问题。避免执行恶意代码或读取敏感信息。
## Python YAML 排序键
我们可以使用dump's sort_keys参数对键进行排序。
sort_keys.py
#!/usr/bin/env python3
import yaml
with open('xx_config.yaml') as f:
data = yaml.load(f, Loader=yaml.FullLoader)
print(data)
sorted = yaml.dump(data, sort_keys=True)
print(sorted)
{'server': {'host': 'localhost', 'port': 8080}, 'database': {'type': 'MySQL', 'host': '127.0.0.1', 'port': 3306, 'username': 'root', 'password': 'password'}, 'logging': {'level': 'info', 'file': 'app.log'}} database: host: 127.0.0.1 password: password port: 3306 type: MySQL username: root logging: file: app.log level: info server: host: localhost port: 8080
该示例从 items.yaml
文件中读取数据,并通过 YAML 输出中的键对数据进行排序。
with open('xx_cfg2.yaml') as f:
data = yaml.scan(f, Loader=yaml.FullLoader)
for token in data:
print(token)
StreamStartToken(encoding=None) BlockMappingStartToken() KeyToken() ScalarToken(plain=True, style=None, value='fruits') ValueToken() BlockEntryToken() ScalarToken(plain=True, style=None, value='apple') BlockEntryToken() ScalarToken(plain=True, style=None, value='banana') BlockEntryToken() ScalarToken(plain=True, style=None, value='cherry') KeyToken() ScalarToken(plain=True, style=None, value='veggies') ValueToken() BlockEntryToken() BlockMappingStartToken() KeyToken() ScalarToken(plain=True, style=None, value='carrot') ValueToken() ScalarToken(plain=True, style=None, value='red') BlockEndToken() BlockEntryToken() BlockMappingStartToken() KeyToken() ScalarToken(plain=True, style=None, value='broccoli') ValueToken() ScalarToken(plain=True, style=None, value='green') BlockEndToken() BlockEntryToken() BlockMappingStartToken() KeyToken() ScalarToken(plain=True, style=None, value='spinach') ValueToken() ScalarToken(plain=True, style=None, value='green') BlockEndToken() BlockEndToken() StreamEndToken()
Python 该示例扫描 YAML 文件并打印记号。