Python optparse, default values, and explicit options
Asked Answered
R

2

6

Take the following rather standard code:

from optparse import OptionParser                         
opts = OptionParser()
opts.add_option('-f', action="store_true")
opts.add_option("-x", dest="x", type="int", default=1)
options, args = opts.parse_args()

Assume that -x and -f are mutually exclusive: when -x and -f are both explicitly present, an error should be reported.

How do I detect if -x is present explicitly? Even if it is not, options list the default value.

One way would be to avoid setting the default value which I rather won't do because --help prints default values nicely.

Another way would be checking sys.argv for instances of -x which is a bit awkward, too, if there's more than one name for -x (that is, a --long-name) and there's more than one pair of mutually exclusive options.

It there an elegant solution for this?

Reconciliatory answered 8/11, 2011 at 4:48 Comment(0)
A
8

Use argparse. There's a section for mutually exclusive groups:

argparse.add_mutually_exclusive_group(required=False)

Create a mutually exclusive group. argparse will make sure that only one of the arguments in the mutually exclusive group was present on the command line:

>>> parser = argparse.ArgumentParser(prog='PROG')
>>> group = parser.add_mutually_exclusive_group()
>>> group.add_argument('--foo', action='store_true')
>>> group.add_argument('--bar', action='store_false')
>>> parser.parse_args(['--foo'])
Namespace(bar=True, foo=True)
>>> parser.parse_args(['--bar'])
Namespace(bar=False, foo=False)
>>> parser.parse_args(['--foo', '--bar'])
usage: PROG [-h] [--foo | --bar]
PROG: error: argument --bar: not allowed with argument --foo

optparse is deprecated anyway.

Arterial answered 8/11, 2011 at 5:18 Comment(0)
S
9

You can accomplish this with optparse using a callback. Building from your code:

from optparse import OptionParser

def set_x(option, opt, value, parser):
    parser.values.x = value
    parser.values.x_set_explicitly = True

opts = OptionParser()
opts.add_option('-f', action="store_true")
opts.add_option("-x", dest="x", type="int", default=1, action='callback',
                callback=set_x)
options, args = opts.parse_args()
opts.values.ensure_value('x_set_explicitly', False)

if options.x_set_explicitly and options.f:
    opts.error('options -x and -f are mutually exclusive')

Let's call this script op.py for now. If I do python op.py -x 1 -f, the response is:

Usage: op.py [options]

op.py: error: options -x and -f are mutually exclusive

Supervene answered 8/11, 2011 at 5:29 Comment(0)
A
8

Use argparse. There's a section for mutually exclusive groups:

argparse.add_mutually_exclusive_group(required=False)

Create a mutually exclusive group. argparse will make sure that only one of the arguments in the mutually exclusive group was present on the command line:

>>> parser = argparse.ArgumentParser(prog='PROG')
>>> group = parser.add_mutually_exclusive_group()
>>> group.add_argument('--foo', action='store_true')
>>> group.add_argument('--bar', action='store_false')
>>> parser.parse_args(['--foo'])
Namespace(bar=True, foo=True)
>>> parser.parse_args(['--bar'])
Namespace(bar=False, foo=False)
>>> parser.parse_args(['--foo', '--bar'])
usage: PROG [-h] [--foo | --bar]
PROG: error: argument --bar: not allowed with argument --foo

optparse is deprecated anyway.

Arterial answered 8/11, 2011 at 5:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.