On the question of customizing the usage
:
The parser constructor takes a usage
parameter. The immediate effect is to set an attribute:
parser = argparse.ArgumentParser( ... usage=custom_usage...)
print(parser.usage)
# should show None or the custom_usage string
Being a normal Python object attribute, you can change it after the parser was created.
usage_str = parser.format_usage()
The format_usage
method ask the parser for create the usage that will be shown in the help (and error messages). If the parser.usage
value is None
, it formats it from the arguments. If a string, it is used as is (I think it fills in values like %(prog)s
).
So you could write a usage string from scratch. Or you could set up the parser, get the current usage string, and edit that to suit your needs. Editing is most likely something you'd do during development, while testing the parser in an IDE. But it could be done on the fly.
A crude example:
In [441]: parser=argparse.ArgumentParser()
In [442]: g=parser.add_mutually_exclusive_group()
In [443]: g.add_argument('--foo')
In [444]: g.add_argument('--bar')
In [445]: ustr = parser.format_usage()
# 'usage: ipython3 [-h] [--foo FOO | --bar BAR]\n'
In [450]: parser.usage = ustr.replace('[','(').replace(']',')')
In [451]: parser.format_usage()
# 'usage: usage: ipython3 (-h) (--foo FOO | --bar BAR)\n'
I've replaced the []
with ()
(even on the -h
:( ).
For now testing logical combinations of the args
attributes is the best choice. Inside the parse_args
functions the parser maintains a list (set actually) of arguments that it has seen. That is used to test for required arguments, and for mutually_exclusive_arguments, but it is not available outside that code.
For store_true
(or false) arguments, just check their truth value. For others I like to test for the default None
. If you use other default
values, test accordingly. A nice thing about None
is that the user cannot give you that value.
Perhaps the most general way to test for arguments is to count the number of attributes which are not None
:
In [461]: args=argparse.Namespace(one=None, tow=2, three=None)
In [462]: ll = ['one','tow','three']
In [463]: sum([getattr(args,l,None) is not None for l in ll])
Out[463]: 1
0
means none are found; >0
at least one present; ==len(ll)
all found; >1
violates mutually exclusivity; '==1' for required mutually exclusive.