3分钟学会Python 常用配置文件处理

一:配置文件

1. 什么是配置文件

配置文件是为程序配置参数和初始设置的文件。一般为文本文件,以ini,conf,cnf,cfg,yaml等作为后缀名。

例如mysql的配置文件my.cnf内容如下:

[mysqld]
# Only allow connections from localhost
bind-address = 0.0.0.0
mysqlx-bind-address = 127.0.0.1
default_authentication_plugin = mysql_native_password

2.配置文件的作用

通过配置文件可以使得代码中的参数根据配置文件进行动态配置,而不用直接修改代码的内部,减少风险提高代码复用。

经典应用场景

  1. 多个函数调用同一参数,这个时候最好进行配置化,改动配置文件就可以修改所有函数

  2. 某个参数需要能够动态改变

3.常见配置文件

3.1 ini/conf/cnf文件

这类配置文件由节(section),键(key),值(value)由一下格式组成。

[section1]
key1=value1
key2=value2
[section2]
key1=value1

3.2 yaml文件

3.2.1 简介

yaml文件本质上是一种标记语言,和普通的配置文件相比它能表示更为复杂的数据结构。

它的基本语法规则如下:

  • 大小写敏感

  • 使用缩进表示层级关系

  • 缩进时不允许使用Tab键,只允许使用空格。

  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可

# 表示行注释

yaml支持三种数据结构:

  • 对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典 (dict)

  • 数组:一组有顺序的值,又称为序列/ 列表(List)

  • 标量:单个值

3.2.2 对象

对象的一组键值对使用冒号结构表示

name: xinlan
person: {name: xinlan, age: 18}

YAML

3.2.3 数组

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

- title
- username
- password
args: [title, username, password]

YAML

3.2.4 组合结构

对象数组可以结合使用,形成组合结构

name: xinlan
age: 18
hobby: [python, 游戏, sport]
ouxiang:
-
name: 刘德华
age: 60
-
name: 任达华
age: 65

YAML

3.2.5 标量

yaml可以表示如下数据类型如下:

  • 字符串 默认字符串不要加引号,如果有特殊字符串,用引号包裹

  • 布尔值 true,false

  • 整数

  • 浮点数

  • Null - 表示null

  • 时间 iso8601 1949-10-01t09:00:00+08:00

  • 日期 1949-10-01

二:解析配置文件

1.ConfigParser模块

python提供内置库ConfigParser用来解析ini格式的配置文件。

[log]
filename=py45.log
debug=false
[mysql]
host=127.0.0.1
database=lemon
user=root
password=123456
port=3306

Ini

from configparser import ConfigParser
config = ConfigParser() # 实例化
config.read('config.ini') # 读取配置文件
print(config.sections()) # 返回所有的section名称字符串,一列表返回
print(config.options('mysql')) # 返回指定section下对应的配置项的所有的字符串名称,以列表返回
print(config.items('log')) # 返回指定section下所有的配置项的键值对,二元元组
print(config.get('mysql', 'port'))
print(config.getint('mysql', 'port')) # 指定类型,帮我们转换类型
print(config["mysql"]['host']) # 直接以字典取值的方式读取ini文件

Python

输出

C:\Users\12446\AppData\Local\Programs\Python\Python39\python.exe D:/Lemon/py45/day19/read_ini.py
['log', 'mysql']
['host', 'database', 'user', 'password', 'port']
[('filename', 'py45.log'), ('debug', 'false')]
3306
3306
127.0.0.1
Process finished with exit code 0

Python

2.pyyaml模块

python解析yaml文件需要安装第三方库pyyaml

pip安装pip install pyyaml

pyyaml库的使用非常简单,它会将整个yaml配置文件内容解析成一个python字典返回。

import yaml
with open('config.yaml', 'r', encoding='utf-8') as f:
config = yaml.load(f, Loader=yaml.FullLoader)
print(config)

Python

输出的是字典

{'log': {'filename': 'py45.log', 'debug': False},
'mysql': {'host': '127.0.0.1',
'database': 'lemon',
'user': 'root',
'password': '123456',
'port': 3306}}

Python

3.配置文件解析模块封装

3.1 功能分析

封装前,我们先考虑一下,这个配置文件解析模块需要哪些功能?

  1. 能够处理多种配置文件

  2. 返回值数据结构一致

3.2 封装成函数

封装思路:

  1. 输入参数为配置文件名,以及配置文件字符编码

  2. 根据配置文件名获取配置文件后缀判断配置文件类型,然后分别处理

  3. ini配置文件解析后处理成字典,其实也可以不出处理,ConfigParser对象支持字典格式的取值

  4. ini配置文件解析的一个重要的问题时,不能自动识别配置类型,所以解耦不是很彻底,有时候需要在引用代码中另外处理。

  5. yaml库直接解析数据为一个字典,且自动识别数据类型,不需要做其他处理。

代码封装如下

from configparser import ConfigParser
import yaml
def get_config(filename, encoding='utf-8'):
"""
获取yaml/ini配置文件中的配置
@param filename: str 文件名
@param encoding: 文件字符编码
"""
# 1. 获取配置文件后缀
suffix = filename.split('.')[-1]
# 2.判断类型
# 3.分别处理
if suffix in ['yaml', 'yml']:
with open(filename, 'r', encoding=encoding) as f:
data = yaml.load(f, Loader=yaml.FullLoader)
else:
conf = ConfigParser()
conf.read(filename)
data = {}
for section in conf.sections():
data[section] = dict(conf.items(section))
# 4. 返回
return data
if __name__ == '__main__':
res = get_config(r'D:\config.yaml')
print(res)

Python

3.3 封装成类

封装思路:

  1. 整体思路和上面的函数封装是一致的

  2. 将解析ini文件和yaml文件的逻辑分开放到两个私有方法中

  3. 因为逻辑本身比较简单,面向对象封装和函数封装没有太多区别

from configparser import ConfigParser
import yaml
class Config:
def __init__(self, filename, encoding='utf-8'):
self.filename = filename
self.encoding = encoding
self.suffix = self.filename.split('.')[-1]
if self.suffix not in ['yaml', 'yml', 'cnf', 'conf', 'ini']:
raise ValueError('不能识别的配置文件后缀:{}'.format(self.suffix))
def parse_ini(self):
"""
解析ini
:return:
"""
conf = ConfigParser()
conf.read(self.filename)
data = {}
for section in conf.sections():
data[section] = dict(conf.items(section))
return data
def parse_yaml(self):
"""
解析yaml
:return:
"""
with open(self.filename, 'r', encoding=self.encoding) as f:
data = yaml.load(f, Loader=yaml.FullLoader)
return data
def parse(self):
"""
解析配置文件
:return:
"""
if self.suffix in ['yaml', 'yml']:
return self.parse_yaml()
else:
return self.parse_ini()
if __name__ == '__main__':
cm = Config(r'D:\config.yaml')
res = cm.parse()
print(res)

Python

4.应用到项目中

一个框架封装的彻不彻底的标准是能否复用,也即是另外一个项目来用时,不需要修改框架的源码。

在我们目前封装的框架中,耦合高的点有:

  1. 日志器调用时的传参

  2. 用例数据文件的路径

  3. 生成报告时的传参

配置文件config.yaml

log:
name: ytest
filename: 'D:\logs\my.log'
debug: true
test_cases_dir: 'D:\cases'
test_data_file: 'D:\data.xlsx'
test_report:
report_dir: 'D:\reports'
title: '测试报告'
desc: '测试报告'
tester: 'k'

YAML

get_config函数解析后:

{'log': {'name': 'ytest',
'filename': 'D:\\my.log',
'debug': True},
'test_cases_dir': 'D:\\cases',
'test_data_file': 'D:\\data.xlsx',
'test_report': {'report_dir': 'D:\\reports',
'title': '份测试报告',
'desc': '测试报告',
'tester': 'chenyongzhi'}}

Python

我们可以将这些写到配置文件中,然后在框架代码中动态的获取配置文件的相对应设置,实现代码的解耦。

common 文件夹下的 __init__.py的文件中调用解析配置文件的函数

from common.log_handler import get_logger
from common.read_excel_tool import get_data_from_excel
from common.congig_handler import get_config
conf = get_config(r'D:\config.yaml') # 在这里将配置文件解析成字典格式返回
logger = get_logger(**conf['log']) # 在这里创建日志器----日志器调用时的传参

Python

cases = get_data_from_excel(conf['test_data_file'], 'login') # ---测试用例数据的路径

Python

import unittest
import unittestreport
from common import conf
if __name__ == '__main__':
discover = unittest.defaultTestLoader.discover(conf['test_cases_dir']) # 表示收集当前目录下所有用例
runner = unittestreport.TestRunner(discover, **conf['test_report'])
runner.run()
posted @   测试玩家勇哥  阅读(535)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
🔑
  1. 1 DAN DAN 心魅かれてく(Cinema Version) FIELD OF VIEW
  2. 2 ロマンティックあげるよ 橋本潮
  3. 3 INNOCENT PRIMEVAL BREAKER GAME VERSION REOL
  4. 4 METAMORPHOSIS INTERWORLD
ロマンティックあげるよ - 橋本潮
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 吉田健美

作曲 : 池毅

おいでファンタジー

好きさミステリー

君の若さ隠さないで

不思議したくて冒険したくて

誰もみんなウズウズしてる

大人のフリしてあきらめちゃ

奇跡の謎など解けないよ

もっとワイルドに

もっとたくましく生きてごらん

ロマンチックあげるよ

ロマンチックあげるよ

ホントの勇気みせてくれたら

ロマンチックあげるよ

ロマンチックあげるよ

トキメク胸に

キラキラ光った夢をあげるよ

いつかワンダフル

きっとビューティフル

人のジャングル迷いこんで

スリルしたくて幸せしたくて

何故かみんなソワソワしてる

思ったとおりに叫ばなきゃ

願いは空まで届かない

もっとセクシーに

もっと美しく生きてごらん

ロマンチックあげるよ

ロマンチックあげるよ

ホントの涙見せてくれたら

ロマンチックあげるよ

ロマンチックあげるよ

淋しい心やさしく包んで

愛をあげるよ

ロマンチックあげるよ

ロマンチックあげるよ

ホントの勇気みせてくれたら

ロマンチックあげるよ

ロマンチックあげるよ

トキメク胸に

キラキラ光った夢をあげるよ