Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Python argparse, is it possible to have paired --no-something/--something arguments?

I'm writing a program in which I would like to have arguments like this:

--[no-]foo   Do (or do not) foo. Default is do. 

Is there a way to get argparse to do this for me?

I was using Python 3.2 here back in 2012.

It turns out that BooleanOptionalAction has been added in Python 3.9's version of argparse and solves this problem, and I've changed my accepted answer to the new one. But, other answers on this page should help if you're still using a Python prior to 3.9.

like image 714
Omnifarious Avatar asked Feb 10 '12 20:02

Omnifarious


People also ask

How do you make Argparse argument optional?

Optional arguments are useful if you want to give the user a choice to enable certain features. To add an optional argument, simply omit the required parameter in add_argument() . args = parser. parse_args()if args.

How does Argparse work in Python?

Python argparse It parses the defined arguments from the sys. argv . The argparse module also automatically generates help and usage messages, and issues errors when users give the program invalid arguments. The argparse is a standard module; we do not need to install it.

What does it mean to parse arguments in Python?

Argument Parsing using sys.Your program will accept an arbitrary number of arguments passed from the command-line (or terminal) while getting executed. The program will print out the arguments that were passed and the total number of arguments.


1 Answers

Well, none of the answers so far are quite satisfactory for a variety of reasons. So here is my own answer:

class ActionNoYes(argparse.Action):     def __init__(self, opt_name, dest, default=True, required=False, help=None):         super(ActionNoYes, self).__init__(['--' + opt_name, '--no-' + opt_name], dest, nargs=0, const=None, default=default, required=required, help=help)     def __call__(self, parser, namespace, values, option_string=None):         if option_string.starts_with('--no-'):             setattr(namespace, self.dest, False)         else:             setattr(namespace, self.dest, True) 

And an example of use:

>>> p = argparse.ArgumentParser() >>> p._add_action(ActionNoYes('foo', 'foo', help="Do (or do not) foo. (default do)")) ActionNoYes(option_strings=['--foo', '--no-foo'], dest='foo', nargs=0, const=None, default=True, type=None, choices=None, help='Do (or do not) foo. (default do)', metavar=None) >>> p.parse_args(['--no-foo', '--foo', '--no-foo']) Namespace(foo=False) >>> p.print_help() usage: -c [-h] [--foo]  optional arguments:   -h, --help       show this help message and exit   --foo, --no-foo  Do (or do not) foo. (default do) 

Unfortunately, the _add_action member function isn't documented, so this isn't 'official' in terms of being supported by the API. Also, Action is mainly a holder class. It has very little behavior on its own. It would be nice if it were possible to use it to customize the help message a bit more. For example saying --[no-]foo at the beginning. But that part is auto-generated by stuff outside the Action class.

like image 112
Omnifarious Avatar answered Sep 28 '22 07:09

Omnifarious