如何结合ArgParse使用simple_settings包的--settings参数?
问题场景
之前使用simple_settings时,直接通过命令行python prog.py --settings=someFolder.settings就能加载./someFolder/settings.py里的配置,无需自行处理参数解析,simple_settings会自动识别该参数。但引入ArgParse后,必须添加--settings的参数定义,否则ArgParse会报错未识别该参数;可一旦添加后,simple_settings又找不到这个参数了,访问配置时会抛出RuntimeError: Invalid settings file [someFolder.settings]。
解决方案
方法1:让simple_settings先处理配置参数,再用ArgParse解析剩余参数
simple_settings的settings对象在导入时会自动扫描sys.argv并处理--settings参数,处理后会将该参数从sys.argv中移除。调整代码顺序,先导入settings,再初始化ArgParse解析其他参数:
from simple_settings import settings from argparse import ArgumentParser if __name__ == '__main__': # simple_settings已自动处理--settings参数并从sys.argv中移除 parser = ArgumentParser() parser.add_argument("-d", "--desk", help="输入工位ID,用法:`python3 thisProg.py -d=<ID>`") args = parser.parse_args() # 正常访问配置项 serv = settings.RT_SERVICE sec = settings.CACHE_DATA_EXPIRY_SECONDS
这样ArgParse只会解析剩余的--desk参数,不会触发未识别参数的报错,同时simple_settings也能正确加载配置。
方法2:手动将ArgParse解析后的settings参数传给simple_settings
如果必须先初始化ArgParse(比如需要先处理其他参数逻辑),可以使用simple_settings的load_settings函数手动加载配置,不依赖其自动扫描命令行的逻辑:
from argparse import ArgumentParser from simple_settings import load_settings if __name__ == '__main__': parser = ArgumentParser() parser.add_argument("-d", "--desk", help="输入工位ID,用法:`python3 thisProg.py -d=<ID>`") parser.add_argument("-s", "--settings", help="指定要加载的配置,用法:`python3 thisProg.py --settings=somefolder.settings`") args = parser.parse_args() # 手动传入配置路径加载配置 settings = load_settings(args.settings) # 访问配置项 serv = settings.RT_SERVICE sec = settings.CACHE_DATA_EXPIRY_SECONDS
这种方式完全由开发者控制配置加载的时机和参数,彻底避免与ArgParse的参数解析逻辑冲突。
核心原因
ArgParse解析参数时会处理所有传入的命令行参数,若定义了--settings,它会将该参数从sys.argv中取出并保存到args对象中,导致后续simple_settings自动扫描时找不到该参数;若不定义--settings,ArgParse则会因遇到未识别参数而报错。通过调整执行顺序或手动加载配置,即可解决两者的逻辑冲突。
内容的提问来源于stack exchange,提问作者Nav

