【发布时间】:2018-04-08 07:02:19
【问题描述】:
如何允许在使用来自子解析器的子命令后添加顶级程序参数?
我有一个程序,其中包含多个子解析器以允许子命令,从而改变程序的行为。以下是它的设置示例:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import argparse
def task_a():
print('did task_a')
def task_c():
print('did task_c')
def task_d():
print('did task_d')
def run_foo(args):
a_arg = args.a
c_arg = args.c
if a_arg:
task_a()
if c_arg:
task_c()
def run_bar(args):
a_arg = args.a
d_arg = args.d
if a_arg:
task_a()
if d_arg:
task_d()
def parse():
'''
Run the program
arg parsing goes here, if program was run as a script
'''
# create the top-level parser
parser = argparse.ArgumentParser()
# add top-level args
parser.add_argument("-a", default = False, action = "store_true", dest = 'a')
# add subparsers
subparsers = parser.add_subparsers(title='subcommands', description='valid subcommands', help='additional help', dest='subparsers')
# create the parser for the "foo" command
parser_foo = subparsers.add_parser('foo')
parser_foo.set_defaults(func = run_foo)
parser_foo.add_argument("-c", default = False, action = "store_true", dest = 'c')
# create the parser for the "bar" downstream command
parser_bar = subparsers.add_parser('bar')
parser_bar.set_defaults(func = run_bar)
parser_bar.add_argument("-d", default = False, action = "store_true", dest = 'd')
# parse the args and run the default parser function
args = parser.parse_args()
args.func(args)
if __name__ == "__main__":
parse()
当我运行程序时,我可以调用一个带有参数的子命令,如下所示:
$ ./subparser_order.py bar -d
did task_d
$ ./subparser_order.py foo -c
did task_c
但如果我想包含顶层的参数,我必须这样称呼它:
$ ./subparser_order.py -a foo -c
did task_a
did task_c
但是,我认为这很令人困惑,特别是如果有很多顶级 args 和很多子命令 args;子命令foo 被夹在中间,难以辨别。
我宁愿能够像subparser_order.py foo -c -a 这样调用程序,但这不起作用:
$ ./subparser_order.py foo -c -a
usage: subparser_order.py [-h] [-a] {foo,bar} ...
subparser_order.py: error: unrecognized arguments: -a
实际上,指定子命令后根本无法调用顶级args:
$ ./subparser_order.py foo -a
usage: subparser_order.py [-h] [-a] {foo,bar} ...
subparser_order.py: error: unrecognized arguments: -a
是否有允许在子命令之后包含顶级参数的解决方案?
【问题讨论】:
-
我尝试使用
add_parser()的parents=参数执行此操作,但我无法弄清楚。看起来子命令中的参数会覆盖顶级参数。但如果你想在一堆子命令之间共享一堆选项,至少这是你应该使用的。