Checking values after parsing is simplest. You can even use parser.error('...')
to produce an error message in the standard argparse
format.
argparse
handles each argument independently, and tries to do so in a way that doesn't care about the order (except for positionals
). Each input value is added to the args
namespace by the corresponding Action
object (its __call__
method). A default store
action simply uses setattr(args, dest, value)
; a store_true
does setattr(args, dest, True)
.
Mutually exclusive groups are handled by keeping a set
of seen_actions
, and checking that against the group's own list of Actions. I've explored generalizing the groups to allow for other logical combinations of actions. As complicated as that has gotten (especially when displaying the usage
), I didn't envisage testing for values as well as occurrence.
It would be possible to write custom Action
classes, that check for co-occurrence, but that gets more complicated.
We could give with-shoes
an Action class that checks the values of the args.animal
attribute, and raises an error if that value is snake
. But what if the user provides the with-shoes
option first? We'd have to give animal
a custom class that checks the args.with_shoes
value, and raise an error if that is True
, etc. So shoes
has to know about animals
and animals
has to know about shoes
. Testing after parsing allows you to put the logic in one place.
One of the big advantages to using a parser like argparse
is it generates the usage, help, and error messages for you. But validation logic like this is hard to express automatically. As it is, the usage formatting for the relatively simple mutually-exclusive logic is brittle and easily broken.
An earlier attempt at answering this kind of question:
Parameter dependencies in Python - can't make it work
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…