Let's say I have a python script with arguments foo [--bar baz]
and want to add an optional argument/switch --extra-info
that would just print some extra information and exit. (My actual use case is bit more complicated, but this illustrates the issue.)
I found the following solution, but it looks more like a hack. Basically, I am making the positional argument optional if '--extra-info' is present in the argument list:
import sys
import argparse
parser.add_argument('--extra-info', action='store_true')
pos_nargs = '?' if '--extra-info' in sys.argv else None
parser.add_argument('foo', nargs=pos_nargs)
parser.add_argument('--bar')
Is there a better approach to this?
I would expect there to be one, given that --help
behaves exactly the way I want my switch to behave...
You can parse the command line in 2 passes: The first pass is to parse --extra-info
, the second will parse the rest.
#!/usr/bin/env python3
import argparse
import sys
parser = argparse.ArgumentParser()
parser.add_argument("--extra-info", action="store_true")
options, remainder = parser.parse_known_args()
if options.extra_info:
print("Show extra information")
sys.exit()
parser = argparse.ArgumentParser()
parser.add_argument("foo")
parser.add_argument("--bar")
# Add here for the help text only
parser.add_argument("--extra-info", action="store_true", help="blah")
options = parser.parse_args(remainder)
print(options)
Some interactions:
# Show help
$ ./main.py
usage: main.py [-h] [--bar BAR] [--extra-info] foo
main.py: error: the following arguments are required: foo
# Show extra info
$ ./main.py --extra-info
Show extra information
# specify foo/bar
$ ./main.py myfoo --bar mybar
Namespace(foo='myfoo', bar='mybar', extra_info=False)
In the first pass, I used parse_known_args
just to parse --extra-info
. The remainder
holds those command-line arguments which the first-pass parser does not understand. We will use this remainder in the second pass.
In the second pass, I added --extra-info
simply for the help/usage.