I would agree that this looks exactly like a sub-parser problem, and that if you don't want to make it an optional argument by using --all
and --name
, one suggestion from me would be just to ignore the all
and name
altogether, and use the following semantics:
- If
tester.py
is called without any arguments, stop all process.
- If
tester.py
is called with some arguments, stop only those processes.
Which can be done using:
import argparse, sys
parser = argparse.ArgumentParser()
parser.add_argument('processes', nargs='*')
parsed = parser.parse(sys.argv[1:])
print parsed
which will behave as follows:
$ python tester.py
Namespace(processes=[])
$ python tester.py proc1
Namespace(processes=['proc1'])
Or, if you insist on your own syntax, you can create a custom class. And actually you're not having a "mutually exclusive group" case, since I assume if all
is specified, you will ignore the rest of the arguments (even when name
is one of the other arguments), and when name
is specified, anything else after that will be regarded as processes' name.
import argparse
import sys
class AllOrName(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
if len(values)==0:
raise argparse.ArgumentError(self, 'too few arguments')
if values[0]=='all':
setattr(namespace, 'all', True)
elif values[0]=='name':
if len(values)==1:
raise argparse.ArgumentError(self, 'please specify at least one process name')
setattr(namespace, 'name', values[1:])
else:
raise argparse.ArgumentError(self, 'only "all" or "name" should be specified')
parser = argparse.ArgumentParser()
parser.add_argument('processes', nargs='*', action=AllOrName)
parsed = parser.parse_args(sys.argv[1:])
print parsed
with the following behaviour:
$ python argparse_test.py name
usage: argparse_test.py [-h] [processes [processes ...]]
argparse_test.py: error: argument processes: please specify at least one process name
$ python argparse_test.py name proc1
Namespace(name=['proc1'], processes=None)
$ python argparse_test.py all
Namespace(all=True, processes=None)
$ python argparse_test.py host
usage: argparse_test.py [-h] [processes [processes ...]]
argparse_test.py: error: argument processes: only "all" or "name" should be specified
$ python argparse_test.py
usage: argparse_test.py [-h] [processes [processes ...]]
argparse_test.py: error: argument processes: too few arguments
all
to--all
andname
to--name
.