使用影响其他配置参数的一个可自定义参数进行配置

时间:2021-04-30 13:27:36

标签: python

我有一个 config.py 文件,其中包含路径和其他常量值:

WORKING_PATH = Path(__file__).resolve().parent

size = 160
order = 4

experiment_dir = WORKING_PATH / 'data/experiment'

...

现在这很容易导入到我的主脚本中,例如只需使用 config.experiment_dir 访问值。

但我想更新代码并使 WORKING_PATH 可定制,输入参数取自 cli。 如果我只是在主函数中覆盖 WORKING_PATH 变量,experiment_dir 变量已经设置为默认的 WORKING_PATH,所以我必须找到更好的解决方案。

处理这个问题的最好和最干净的方法是什么,同时保持简单?

此外,在我的配置中找到的路径在不同的函数中被多次引用,所以我想避免只将配置作为参数传递给每个地方。我希望它可以在任何地方访问,并希望保持与以前相同的语法(例如 config.experiment_dir),因此我不必更改所有配置访问权限。

我想我可以将配置变成一个类,使用 WORKING_PATH 作为可自定义的属性,但我必须在我的主函数中将其设置为 global,以避免传递它处处作为参数。我不确定这是一个非常干净的解决方案。或者有没有办法使用静态类来做到这一点,但有一个可以更改的变量?

编辑:我想我可以只使用我拥有的覆盖解决方案,但是将依赖于 WORKING_PATH 的参数包装在每个它们自己的函数中,例如:

def experiment_dir():
    return WORKING_PATH / 'data/experiment'

不过,我只需要通过向所有这些引用添加 () 来调整代码。但是这样一来,experiment_dir 之类的变量就不会在程序开始时设置,每次引用时都会检查 WORKING_PATH。同样,我不确定这有多干净,因为配置的某些参数现在可以作为带有 () 的函数访问,而有些则不会使用 (),作为普通变量。

1 个答案:

答案 0 :(得分:0)

全局变量并不意味着要更改,但您可以使用 global,我会将所有需要更改的变量包装在具有某些动态功能的类中。

import os

SIZE = 160
ORDER = 4

class CFP:

    cwd = None

    exp_dir = None
    exp_rel_path = 'data/experiment'

    def __init__(self, path=__file__, **kwargs):
        self.update_to(path, **kwargs)

    def update_to(self, fname, **kwargs):
        for k in kwargs:
            self.__dict__[k] = kwargs[k]

        if not os.path.isdir(fname):
            self.cwd = os.path.abspath(
                os.path.dirname(fname))
        else:
            self.cwd = os.path.abspath(fname)

        self.exp_dir = os.path.join(
            self.cwd, *self.pharsed_join(self.exp_rel_path)
        )
        self.__check_all()

    def __check_all(self):
        for p in self.__dict__:
            if 'rel' not in p:
                path = self.__dict__[p]
                if not os.path.exists(path):
                    raise FileExistsError(path)

    @staticmethod
    def pharsed_join(pstr):
        if '/' in pstr:
            return pstr.split('/')
        return [pstr]

from config_vars import *

config = CFP(exp_rel_path='files')

if __name__ == '__main__':
    print(config.exp_dir)
    config.update_to('./build', exp_rel_path='o-console')
    print(config.exp_dir)

相关问题