In a program using argparse
with subcommands, I want to add arguments to control verbosity. I would like these to act as "global" arguments, meaning it shouldn't matter whether they are passed before or after the subcommand. In other words, I want the following invocations to be interpreted the same way:
> ./test.py -v -v foo
> ./test.py foo -v -v
> ./test.py -v foo -v
Things I've tried
Adding the arguments to the parent parser and the subcommand parser:
main = arg.ArgumentParser()
main.add_argument ("-v", "--verbose", default = 0, action = "count")
s = main.add_subparsers()
foo = s.add_parser ("foo")
foo.add_argument ("-v", "--verbose", default = 0, action = "count")
print (main.parse_args().verbose)
This gives (all should be 2):
Invocation | Result |
---|---|
./test.py -v -v foo |
0 |
./test.py foo -v -v |
2 |
./test.py -v foo -v |
1 |
Adding a common "parent" parser to both the main and subcommand parsers:
Inspired by this question, the difference being that in the other question only a single subcommand is active at a time, whereas here the main parser and the subcommand parser are both active simultaneously.
p = arg.ArgumentParser (add_help = False)
p.add_argument ("-v", "--verbose", default = 0, action = "count")
main = arg.ArgumentParser (parents = [ p ])
s = main.add_subparsers()
foo = s.add_parser ("foo", parents = [ p ])
print (main.parse_args().verbose)
This gives the same result as above.
Declaring the main parser as parent for the subcommand parser:
main = arg.ArgumentParser()
main.add_argument ("-v", "--verbose", default = 0, action = "count")
s = main.add_subparsers()
foo = s.add_parser ("foo", parents = [ main ], add_help = False)
print (main.parse_args().verbose)
This results in an infinite recursion where the foo
subcommand expects itself:
> ./test.py -v -v foo
usage: test.py foo [-h] [-v] {foo} ...
test.py foo: error: too few arguments
Adding the arguments to the parent and subcommand parsers with different destinations:
main = arg.ArgumentParser()
main.add_argument ("-v", "--verbose", default = 0, action = "count", dest = "main_verbose")
s = main.add_subparsers()
foo = s.add_parser ("foo")
foo.add_argument ("-v", "--verbose", default = 0, action = "count")
args = main.parse_args()
print (args.main_verbose + args.verbose)
This works, but it adds complexity: now I need to combine the values for each common parameter and for as many layers as I have nested subcommands.
Is there a way to define "global" parameters, that will act the same no matter where they are put on the command-line?