How can you allow for top-level program arguments to be added after using a subcommand from a subparser?
I have a program that includes several subparsers to allow for subcommands, changing the behavior of the program. Here is an example of how its set up:
#!/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()
When I run the program I can call a subcommand with its args like this:
$ ./subparser_order.py bar -d
did task_d
$ ./subparser_order.py foo -c
did task_c
But if I want to include the args from the top level, I have to call it like this:
$ ./subparser_order.py -a foo -c
did task_a
did task_c
However, I think this is confusing, especially if there are many top-level args and many subcommand args; the subcommand foo
is sandwiched in the middle here and harder to discern.
I would rather be able to call the program like subparser_order.py foo -c -a
, but this does not work:
$ ./subparser_order.py foo -c -a
usage: subparser_order.py [-h] [-a] {foo,bar} ...
subparser_order.py: error: unrecognized arguments: -a
In fact, you cannot call the top-level args at all after specifying a subcommand:
$ ./subparser_order.py foo -a
usage: subparser_order.py [-h] [-a] {foo,bar} ...
subparser_order.py: error: unrecognized arguments: -a
Is there a solution that will allow for the top-level args to be included after the subcommand?