我有一个 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。同样,我不确定这有多干净,因为配置的某些参数现在可以作为带有 () 的函数访问,而有些则不会使用 (),作为普通变量。
答案 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)