スクリプト用のコマンドライン インターフェイスを作成しています。ユーザーがコマンドライン自体または構成ファイルでオプションを提供できるようにしたいと思います。
特定のオプションには妥当なデフォルトがあります。私が欲しいロジックはこれです:
- オプションがコマンドラインにも設定ファイルにもない場合は、デフォルトを使用してください。
- オプションが構成ファイルのみ、またはコマンド ラインのみにある場合は、そのオプションを使用します。
- オプションが構成ファイルとコマンド ラインの両方にある場合は、明示的なコマンド ラインが優先されます。
たとえば、ここに私の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
のいずれかを与えることです。それがデフォルトによるものかどうかを知る方法はありません。さらに、docstring でデフォルトを指定したいと思います。これは、ユーザーの観点からははるかに優れています。{"--delay": "1"}
{"--delay": "5"}
これを達成するための良い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)