I'm using argparse
to manage command line options, and I want manage two options, --check
and --nocheck
.
I'm actually doing something like this in mybadscript.py
:
[...]
args = parser.parse_args()
if args.check:
check = True
if args.nocheck:
check = False
[...]
The problem is that if launch the script this way:
python mybadscript.py --nocheck --check
check
will be set to False
. This is incorrect, since the last option is --check
.
How can I correctly manage them?
PS: I know you can easily avoid it using only one option, but I would know how I can manage option precedence with argparse
, since you can encounter it in more complicated scenarios.
PPS: the suggested answer does incidentally answer my question, but the related question is not the same one.
See the argparse documentation. Here's an example of what you might want. I've included several options you may not need—I thought that was better than leaving them off and you needing them.
>>> parser = argparse.ArgumentParser()
>>> group = parser.add_mutually_exclusive_group(required=True)
>>> group.add_argument('--check', action='store_true', dest="check")
>>> group.add_argument('--nocheck', action='store_false', dest="check")
>>> parser.parse_args(["--check"])
Namespace(check=True)
>>> parser.parse_args(["--nocheck"])
Namespace(check=False)
You may not want the mutually exclusive part—in that case delete the second line and replace group
with parser
. If you do so you may wish to add this line:
>>> parser.set_defaults(check=False)
You have two arguments that independently set two different Namespace attributes, args.check
and args.nocheck
. With --nocheck --check
input line, both are set.
In:
if args.check:
check = True
if args.nocheck:
check = False
you test nocheck
last, so that one overrides check
.
argparse
tries to handle optionals (flagged arguments) in an order independent manner.
If they write to the same 'dest', it's the last one that you will end up seeing. One way to see what was entered, and in what order, is to use an 'append' action:
parser=argparse.ArgumentParser()
parser.add_argument('--check', dest='checked', action='append_const', const=True)
parser.add_argument('--nocheck', dest='checked', action='append_const', const=False)
In [14]: parser.parse_args(''.split()) # no arg
Out[14]: Namespace(checked=None)
I could have made the default []
In [15]: parser.parse_args('--check'.split())
Out[15]: Namespace(checked=[True])
In [16]: parser.parse_args('--nocheck'.split())
Out[16]: Namespace(checked=[False])
In [17]: parser.parse_args('--nocheck --check --nocheck'.split())
Out[17]: Namespace(checked=[False, True, False])
The paired 'store_true' and 'store_false' in the other answer is simpler.
Better yet, choose one as the default choice, and just provide an option for the other. As long as the default is clear, there really isn't a need for both arguments.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With