Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

argparse: How to make mutually exclusive arguments optional?

I want to use my script like this:

python test.py run
python test.py stop

and my code is like this:

parser = argparse.ArgumentParser()
command_group = parser.add_mutually_exclusive_group(required=True)
command_group.add_argument('run', help='run it', action='store_true')
command_group.add_argument('stop', help='stop it', action='store_true')

when I execute it, an exception is raised:

ValueError: mutually exclusive arguments must be optional

so I try to add required=False when I add each argument.Then I get another exception:

TypeError: 'required' is an invalid argument for positionals

I'm confused.

like image 357
huron Avatar asked Aug 23 '16 04:08

huron


2 Answers

A better way to do this is to add a single positional argument that can have two choices. Since you want it to be optional, use nargs='?', which means zero or one times:

parser = argparse.ArgumentParser()
parser.add_argument('run', help='run or stop', nargs='?', choices=('run', 'stop'))

If run is given, the value will be 'run'. If stop is given, it will be 'stop'. If neither is given, it will be None.


If you really want to use a mutually-exclusive group, I'm not sure if you can do it exactly how you want. You can, however, make them optional arguments by adding a hyphen:

import argparse

parser = argparse.ArgumentParser()
command_group = parser.add_mutually_exclusive_group()
command_group.add_argument('-run', help='run it', action='store_true')
command_group.add_argument('-stop', help='stop it', action='store_true')

Of course the problem with that is that the user also needs to provide the hyphen, but that's the sort of problem you can expect if you limit yourself like that.

like image 60
zondo Avatar answered Nov 05 '22 17:11

zondo


You can achieve this with nargs='?'

parser = argparse.ArgumentParser()
command_group = parser.add_mutually_exclusive_group()
command_group.add_argument('run', help='run it', nargs='?')
command_group.add_argument('stop', help='stop it', nargs='?')

Which would allow you to call the program with

python test.py run

or

python test.py stop

but not

python test.py run stop
like image 34
Steen Avatar answered Nov 05 '22 18:11

Steen