Ruby has this very nice feature when you define options with optparse:
opts.on('--[no-]flag', "Set flag.") do |p|
options.persistPost=p
end
which allows you to have the --flag and --no-flag options for free. Python does not have this, but there are a 3 options to go around that.
The verbose way
Just define 2 options.
parser.add_argument(
'--flag',
dest='flag',
action='store_true',
help='Set flag',
)
parser.add_argument(
'--no-flag',
dest='flag',
action='store_false',
help='Unset flag',
)
Custom action
You can give a custom action to the action parameter of add_argument. This custom action can look at the actual option given and act accordingly.
parser.add_argument(
'--flag', '--no-flag',
dest='flag',
action=BooleanAction,
help='Set flag',
)
BooleanAction is just a tiny 6 lines class, defined as follow:
class BooleanAction(argparse.Action):
def __init__(self, option_strings, dest, nargs=None, **kwargs):
super(BooleanAction, self).__init__(option_strings, dest, nargs=0, **kwargs)
def __call__(self, parser, namespace, values, option_string=None):
setattr(namespace, self.dest, False if option_string.startswith('--no') else True)
As you can see, it just looks at the name of the flag, and if it starts with --no, the destination will be set to False.
Custom parser
Create your own add_argument method, which can then automagically add the --no option for you.
First define your own parser:
class BoolArgParse(argparse.ArgumentParser):
def add_bool_arguments(self, *args, **kw):
grp = self.add_mutually_exclusive_group()
# add --flag
grp.add_argument(*args, action='store_true', **kw)
nohelp = 'no ' + kw['help']
del kw['help']
# add --no-flag
grp.add_argument('--no-' + args[0][2:], *args[1:], action='store_false', help=nohelp, **kw)
Then use it:
parser = BoolArgParse()
parser.add_bool_arguments('--flag',dest='flag', help='set flag.')
Comparison
I do not want to say plus and min points as not all use cases want the same features, but there you are:
- Verbose way:
- More lines of code (need to define 2 flags),
- Help more verbose,
- Easy (no extra class),
- Possibility to have the same parameter multiple times, the last one wins (eg. --flag --no-flag).
- Custom action:
- Less lines of code,
- Help not verbose (only one line of help),
- Possibility to have the same parameter multiple times, the last one wins (eg. --flag --no-flag).
- Custom parser
- The most lines of codes,
- Help verbose but grouped,
- Cannot have the same flag repeated.
The Custom Action (BooleanAction ) won’t include the “–no-” version int the list of flags, only in the descriptions of the arguments.
In case you find this and are using Python >= 3.9, you can use BooleanOptionalAction which is now built-in:
https://docs.python.org/3/library/argparse.html#:~:text=same%20interface.%20The-,BooleanOptionalAction,-is%20available%20in
parser.add_argument(
“–force”,
action=argparse.BooleanOptionalAction,
help=”Remove existing directory if found. WARNING: Will delete your data and is not reversable!”,
)