Bootstrap

python3 读取配置文件,重载配置文件

前言:

-- 配置 是一个变量,是一个全局类实例。

 

用法:

1. 普通用法,读取并获值:

(1)配置.set( "filePath" )

(2)配置.get( "a.b.c" )

 

 

2. 高级用法,重载配置

(1)设置数据源

配置.set( "配置文件路径" )

 

(2)设置数据源与变量的关联关系

变量集 = { "a":"未赋值" }

关联表 = { "a":"输出字符" }     # 关联表格式为,变量集的key : 数据源的key 

配置.link( 变量集,关联表 )

 

(3)重载配置,读取数据源,覆写变量值

配置.reload()

 

另:

一个实例一般只对应一个配置文件,用 配置类.实例化() 来获取新实例。

用export方法还可以生成配置文件。

from u_工具 import *

conf = {
    "a1":1,
    "a2": {
        "b1":2,
        "b2":{
            "c1":3
        }
    },
    "a3":"3",
    "a4":"4"
}

配置.set("配置文件.json").link(conf).export().reload()
# 配置.all("配置文件.json",conf)
print(getDictValue(conf, "a2.b2.c1"))

time.sleep(20)
# 趁机改改配置

配置.reload()
# 配置.get("a2.b2.c1")
print(getDictValue(conf, "a2.b2.c1"))

 

 

 

附:工具类.py

import json
import time
from pathlib import Path



# 获取多层dict的值
def getDictValue(my_dict, key="", default=None, 分隔符="."):
    if not key:
        if default:
            return default
        else:
            return my_dict

    try:
        start_index = 0
        end_index = len(key) - 1
        if key[0] == 分隔符: start_index += 1
        if key[end_index] == 分隔符: end_index -= 1
        key = key[start_index:end_index+1]
        keys = key.split(分隔符)
        for key in keys:
            if isinstance(my_dict, list):
                my_dict = my_dict[int(key)]
            else:
                my_dict = my_dict[key]
        return my_dict
    except:
        return default



# 设置多层dict的值
def setDictValue(mydict,key,value,分隔符='.'):
    keys = key.split(分隔符)
    length = len(keys)
    for index,i in enumerate(key.split(分隔符)):
        if int(index)+1 == length:
            if isinstance(mydict, list):
                mydict[int(i)] = value
            else:
                mydict[i] = value
        else:
            if isinstance(mydict, list):
                mydict = mydict[int(i)]
            else:
                mydict = mydict[i]




# region 配置相关
import configparser

def _configparser_to_dict(config):
    my_dict = dict(config._sections)
    for key in my_dict:
        my_dict[key] = dict(my_dict[key])
    return my_dict


class 配置类:

    @staticmethod
    def 实例化():
        return 配置类()

    def __init__(self):
        self.数据源 = {}
        self.配置 = {}
        self.变量集 = {}
        self.关联表 = {}

    def _数据源转dict(self):
        路径 = self.数据源["路径"]
        类型 = self.数据源["类型"]
        来源 = self.数据源["来源"]

        if (not 类型) or 类型 == "auto":
            类型 = os.path.splitext(路径)[-1][1:].lower()

        try:
            if 类型 == "json":
                if 来源 == "filesystem" or 来源 == "file_system" or 来源 == "file" or 来源 == "fs":
                    dict配置 = json.loads(Path(路径).read_text(encoding='UTF-8'))
                else:
                    raise Exception("配置加载失败,来源不支持")
            else:
                config = configparser.ConfigParser()
                config.read(路径,encoding='UTF-8')
                dict配置 = _configparser_to_dict(config)
        except:
            dict配置 = {}

        return dict配置

    def _设置数据源(self,路径,类型,来源):
        self.数据源["路径"] = 路径
        self.数据源["类型"] = 类型.lower()
        self.数据源["来源"] = 来源.lower()
        return self

    def _get_dict_keyLocation_list(self, mydict={}, 分隔符=".", 前缀="", rstList=[]):
        for i in mydict.keys():
            if not 前缀:
                临时前缀 = f"{i}"
            else:
                临时前缀 = f"{前缀}{分隔符}{i}"

            if isinstance(mydict[i], dict):
                self._get_dict_keyLocation_list(mydict[i], 分隔符, 临时前缀, rstList)
            else:
                rstList.append(临时前缀)

        return rstList


    def 加载(self,路径="./配置文件.json",类型="auto",来源="filesystem"):
        self.配置 = self._设置数据源(路径,类型,来源)._数据源转dict()
        return self

    def 取值(self, key = "", 分隔符 = "."):
        return getDictValue(self.配置, key, 分隔符)

    def 关联(self, 变量集, 关联表 = {}, 分隔符="."):
        if not 关联表:
            关联表 = {}
            keyLocation = self._get_dict_keyLocation_list(变量集,分隔符=分隔符)
            for i in keyLocation:
                关联表[i] = i
        self.变量集 = 变量集
        self.关联表 = 关联表
        return self

    def 重载(self, 分隔符 = ".", is_override_vars = True):
        # 加载配置
        self.配置 = self._数据源转dict()

        if is_override_vars:
            # 覆写变量
            for key in self.关联表.keys():
                old_value = getDictValue(self.变量集,key,分隔符=分隔符)
                now_value = getDictValue(self.配置, self.关联表.get(key), old_value , 分隔符)
                setDictValue(self.变量集,key,now_value)

        return self


    def set(self,路径="./配置文件.json",类型="auto",来源="filesystem"):
        return self.加载(路径,类型,来源)

    def get(self, key = "", 分隔符 = "."):
        return self.取值(key, 分隔符)

    def link(self, 变量集, 关联表 = {}, 分隔符="."):
        return self.关联(变量集, 关联表, 分隔符=分隔符)

    def reload(self, 分隔符 = ".", is_override_vars = True):
        return self.重载(分隔符, is_override_vars)

    def export(self, is_del_before = False, vars ={}):
        config_filePath = self.数据源["路径"]
        is_file_exist = os.path.exists(config_filePath)

        if is_file_exist:
            if is_del_before:
                os.remove(config_filePath)
            else:
                return self

        所在目录 = os.path.dirname(config_filePath)
        if 所在目录:
            if not os.path.exists(所在目录):
                os.makedirs(所在目录)
                
        if not vars:
            vars = self.变量集
        with open(config_filePath, 'w', encoding='utf-8') as f:
            json.dump(vars, f, ensure_ascii=False, indent=2)

        return self


    def all(self, 配置文件路径, 变量集, 类型="auto", 来源="filesystem", 关联表 = {}, 分隔符 = ".", is_del_before = False, export_vars = {}, is_override_vars = True):
        return self.set(配置文件路径,类型,来源).link(变量集,关联表,分隔符=分隔符).export(is_del_before,export_vars).reload(分隔符, is_override_vars)



配置 = 配置类.实例化()


# endregion 配置相关

 

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;