I would like to use argparse
to make some code to be used in the following two ways:
./tester.py all
./tester.py name someprocess
i.e. either all
is specified OR name
with some additional string.
I have tried to implement as follows:
import argparse
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument('all', action='store_true', \
help = "Stops all processes")
group.add_argument('name', \
help = "Stops the named process")
print parser.parse_args()
which gives me an error
ValueError: mutually exclusive arguments must be optional
Any idea how to do it right? I also would like to avoid sub parsers in this case.
The question is a year old, but since all the answers suggest a different syntax, I'll give something closer to the OP.
First, the problems with the OP code:
A positional store_true
does not make sense (even if it is allowed). It requires no arguments, so it is always True
. Giving an 'all' will produce error: unrecognized arguments: all
.
The other argument takes one value and assigns it to the name
attribute. It does not accept an additional process
value.
Regarding the mutually_exclusive_group
. That error message is raised even before parse_args
. For such a group to make sense, all the alternatives have to be optional. That means either having a --
flag, or be a postional with nargs
equal to ?
or *
. And doesn't make sense to have more than one such positional in the group.
The simplest alternative to using --all
and --name
, would be something like this:
p=argparse.ArgumentParser()
p.add_argument('mode', choices=['all','name'])
p.add_argument('process',nargs='?')
def foo(args):
if args.mode == 'all' and args.process:
pass # can ignore the process value or raise a error
if args.mode == 'name' and args.process is None:
p.error('name mode requires a process')
args = p.parse_args()
foo(args) # now test the namespace for correct `process` argument.
Accepted namespaces would look like:
Namespace(mode='name', process='process1')
Namespace(mode='all', process=None)
choices
imitates the behavior of a subparsers argument. Doing your own tests after parse_args
is often simpler than making argparse
do something special.
import argparse
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-a','--all', action='store_true', \
help = "Stops all processes")
group.add_argument('-n','--name', \
help = "Stops the named process")
print parser.parse_args()
./tester.py -h
usage: zx.py [-h] (-a | -n NAME)
optional arguments:
-h, --help show this help message and exit
-a, --all Stops all processes
-n NAME, --name NAME Stops the named process
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With