我正在为我的脚本创建一个命令行界面 . 我希望用户能够在命令行本身或配置文件中提供选项 .
某些选项具有合理的默认值 . 我想要的逻辑是这样的:
-
如果该选项既不在命令行中也不在配置文件中,请使用默认值 .
-
如果该选项仅在配置文件中,或仅在命令行中,请使用该选项 .
-
如果该选项同时位于配置文件和命令行中,则显式命令行优先 .
例如,这是我的docstring:
"""Usage: my-script.py [options] <some_arg>
Options:
-c --config=<file> Configuration file, if it exists.
[default: settings.yaml]
-d --delay=<delay> Delay before scraping each message, to avoid rate
limiting. Delays by a gaussian distribution with
average <delay> and standard deviation <delay>/2.
[default: 1]
"""
所以,没有 settings.yaml
我想要:
$ python my-script.py foo # delay is "1"
$ python my-script.py -d 5 foo # delay is "5"
并且 settings.yaml
的 delay: 10
我希望:
$ python my-script.py foo # delay is "10"
$ python my-script.py -d 5 foo # delay is "5"
我遇到的问题是 docopt
只给了我 {"--delay": "1"}
或 {"--delay": "5"}
. 我无法知道它是否来自默认值 . 此外, I want to specify the default in the docstring - 从用户的角度来看,这更好 .
是否有任何好的docopt-y,Pythonic方法来实现这一目标?我正在考虑针对默认参数检查解析的参数,但是如果碰巧与参数值匹配,则用户将无法使用命令行参数覆盖配置文件参数 .
这是我加载配置文件的方式:
args = docopt(__doc__, version='Yahoo! Groups Backup-er 0.1',
options_first=True)
cfg_args = {}
if args['--config'] != 'settings.yaml' and not os.path.exists(args['--config']):
sys.exit("Specified config file '%s' does not exist." % args['--config'])
if os.path.exists(args['--config']):
settings = yaml.load(open(args['--config']))
command_line_args = args
args = {}
for key, val in settings.items():
args['--%s' % key] = val
args.update(command_line_args)