python--配置文件以及ConfigParser使用

Python
362
0
0
2023-03-14

在项目中通常我们把超参,魔数等需要配置项写入一个配置文件中,方便配置项调整。python项目中通用的配置文件格式有py.ini,json,yml。本文对这些常用形式的配置进行详细讲解。

py配置

使用.py进行配置对于python项目是最简单的形式,不用任何解析操作直接使用。但是对于多平台使用项目,配置项通常是需要通用等,py配置就不易于移植了。

简单的py配置和使用比较简单,直接上代码:

新建conf_py.py

arg_int = 123
arg_str = "123"
arg_list = [1,2,3]
arg_dic = {"a":1,"b":2,"c":3}

from conf_py import *
def parse_py():
    print("arg_int", arg_int)
    print("arg_int", arg_str)
    print("arg_int", arg_list)
    print("arg_int", arg_dic["a"])

ini配置

ini 文件是Initialization File的缩写,即初始化文件,是windows的系统配置文件所采用的存储格式。文件格式:INI文件由节、键、值组成。(文件名也不一定非要ini后缀,你也可以使用cfg等)。格式如下:

节[section]

参数

name=value

举例:

[loggers]
keys = root,main

[handlers]
keys = consoleHandler,fileHandler

[logger_root]
level = INFO
handlers = consoleHandler

[logger_main]
level = INFO
qualname = main
handlers = fileHandler

[typing]
arg_int = 123
arg_str = 123
arg_bool = true
arg_list = [1,2,3]

读取文件后需要使用python的 ConfigParser 配置文件解析器

def parse_ini(ini_path):
    config = configparser.ConfigParser()
    config.read(ini_path)
    # sections获取所有节点
    print("read ini file:\n")
    for section in config.sections():
        print("section", section)
        for key in config[section]:
            print("{} : {}".format(key, config[section][key]))
    # 读取某一项配置文件
    print("config loggers key = ", config["loggers"]["keys"])
    val = config.get('loggers', 'keys')  # 获取指定节点的指定key的value
    print("config loggers key = ", val)
    # 读取各种类型变量,都是str类型
    vals =  dict(config["typing"])
    # config typing =  {'arg_int': '123', 'arg_str': '123', 'arg_bool': 'true', 'arg_list': '[1,2,3]'}
    print("config vals = ", vals)
    # 但是可以强制转换,如果类型转换失败会抛出异常
    an_int = config.getint('typing', 'arg_int')
    print("config arg_int = ", an_int, type(an_int))
    a_bool = config.getboolean('typing', 'arg_bool')
    print("config a_bool = ", a_bool, type(a_bool))

    # 添加一个节点,节点名为add_section, 并写进ini文件
    config.add_section("add_node")
    # 添加键值对
    config["add_node"]["test"]= "test"
    # 修改键值对
    config.set('add_node', 'test', 'test1')
    # 添加键值对
    config.set('add_node', 'test2', 'test2')
    config.write(open(ini_path, "w"))
    # 删除节点
    # 删除键值
    config.remove_option('add_node', 'test2')
    config.remove_section("add_node")
    config.write(open(ini_path, "w"))

ConfigParser解析命令行参数

在上节我们提到了ConfigParser,并使用parser解析配置文件,对配置文件进行增删改。这节我们详细介绍ConfigParser如何解析命令行参数。

def parse_args():
    '''解析命令行参数
    '''
    # 命令行按顺带参数
    # python main.py conf.ini-->['main.py', 'conf.ini' 'debug']
    print(sys.argv)

    # 或者根据argparse格式添加参数
    parser = argparse.ArgumentParser(
    description='工程参数描述',
    epilog=" description参数后显示额外的对程序的描述")
    parser.print_help()

    parser.add_argument('-c', "--cfg", default='conf.ini')
    parser.add_argument('-v', "--mode", default='debug')
    args = parser.parse_args()
    # python main.py -c conf.ini -m release -> args Namespace(cfg='conf.ini', mode='release')
    print("args", args)
    mode = args.mode
    cfg = args.cfg
    print("args", mode, cfg)

以上代码在启动时可以设置启动配置文件和version。

python main.py -c conf.ini -m release

1. 在代码中通过parser.add_argument()设置在启动脚本时可配置参数

2. 启动脚本时对配置项设定值

3. 通过ConfigParser解析参数,cfg='conf.ini', mode='release'

4. 代码中通过args.mode得到启动脚本设置对mode

以上是最简单的命令行脚本启动设置。在使用中我们还可以选择更多的设置:

 """
    add_argument的一些参数属性
    name or flags - 一个命名或者一个选项字符串的列表,例如 foo 或 -f, --foo。
    action - 当参数在命令行中出现时使用的动作基本类型。
    nargs - 命令行参数应当消耗的数目。
    const - 被一些 action 和 nargs 选择所需求的常数。
    default - 当参数未在命令行中出现并且也不存在于命名空间对象时所产生的值。
    type - 命令行参数应当被转换成的类型。
    choices - 可用的参数的容器。
    required - 此命令行选项是否可省略 (仅选项可用)。
    help - 一个此选项作用的简单描述。
    metavar - 在使用方法消息中使用的参数值示例。
    dest - 被添加到 parse_args() 所返回对象上的属性名。
    """

下面我们对常用的配置进行解释

配置参数的类型,使用type制定:

def parse_args_type():
    parser = argparse.ArgumentParser()
    parser.add_argument('count', type=int)
    parser.add_argument('distance', type=float)
    parser.add_argument('street', type=ascii)
    parser.add_argument('code_point', type=ord)
    parser.add_argument('source_file', type=open)
    parser.add_argument('dest_file', type=argparse.FileType('w', encoding='latin-1'))
    parser.add_argument('datapath', type=pathlib.Path)
    args = parser.parse_args()
    print(args)

对action进行指定,action指定的动作有'store_const',store_true','store_true','append'。

需要注意点是,如果'-a', action='store_true',说明默认值是False;如果在命令行进行了设置

-a 则为True;如果'-b', action='store_true' ,default=True ,说明默认值是True。

def parse_args_action():
    # action命名参数指定了这个命令行参数应当如何处理。供应的动作有'store_const',store_true','store_true','append'等。
    # 我们介绍常用的几个动作
    parser = argparse.ArgumentParser()
    # 默认值为false,离谱
    parser.add_argument('--pa', '-a', action='store_true')
    parser.add_argument('--pb', '-b', action="store_true", default=True)
    parser.add_argument('--pc', '-c', action="store_true", default=False)
    # 默认值为true
    parser.add_argument('--pd', '-d', action='store_false')
    parser.add_argument('--pe', '-e', action="store_false", default=True)
    parser.add_argument('--pf', '-f', action="store_false", default=False)
    # args = parser.parse_args()
    # print("a={}, b={}, c={}, d={}, e={} ,f={}".format(args.pa ,args.pb, args.pc, args.pd, args.pe, args.pf))
    # 命令行没有指定,使用默认值
    # python main.py-->a=False, b=True, c=False, d=False, e=True ,f=False
    # 命令行指定参数,action_true/false起作用
    # python main.py -a -b -c -d -e -f-->a=True, b=True, c=True, d=False, e=False ,f=False

    # 如果你在使用时没有调用它,是不会自动初始化为'const'字段中的值,离谱
    parser.add_argument('--const', action='store_const', const=36)
    # args = parser.parse_args()
    # python main.py -->const==None; python main.py --const-->const=36
    # print("const={}".format(args.const))


    parser.add_argument('--append', action='append')
    # args = parser.parse_args()
    # python main.py --append 1 --append 3 --append 4 ->append=['1', '3', '4']
    # print("append={}".format(args.append))

    # 'count' - 计算一个关键字参数出现的数目或次数
    parser.add_argument('--verbose', '-v', action='count', default=0)
    args = parser.parse_args()
    # python main.py -vvvv ->verbose=4
    print("verbose={}".format(args.verbose))

json配置

json也是比较常用的配置文件,其使用也比较简单,使用上节介绍的命令行参数配置json文件,然后使用json库进行解析就好。

import json
def parse_json(json_path):
    """
    json是比较常用的配置文件格式,我们也可以通过命令行将json文件读入,转给json格式来读取配置
    load() 从json文件中读取json格式数据
    loads() 将字符串类型数据转化为json格式数据
    dump() 将json格式数据保存到文件
    dumps() 将json格式数据保存为字符串类型
    :param json_path:
    :return:
    """
    with open(json_path, 'r') as f:
        text = f.read()
    paras = json.loads(text)
    print("paras", paras)
    print("paras valus", paras["class1"]["key3"])

yml配置

同理,yml文件配置使用yaml库解析。

yml和ini文件类似格式,使用段和健值对方式。

public:
    name: yourname
    age: 22
teacher:
    subject: computer
    class: 3rd grade
student:
    id: 123454å
import yaml
def parse_yml(yml_path):
    with open(yml_path) as file:
        cfg = yaml.safe_load(file)
    public_args = cfg["public"]
    print("public_args", public_args)
    teacher_args = public_args.copy()
    teacher_args.update(cfg["teacher"])
    print("teacher_args", teacher_args)
    student_args = public_args.copy()
    student_args.update(cfg["student"])
    print("student_args", student_args)

参考:

https://docs.python.org/zh-cn/3/library/argparse.html