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!”,
)