With a mutually exclusive group I can create a reasonable approximation:
In an interactive session:
In [10]: parser=argparse.ArgumentParser()
In [11]: grp=parser.add_mutually_exclusive_group(required=True)
In [12]: a=grp.add_argument('pos',nargs='?',type=int,default=0)
In [13]: b=grp.add_argument('-n','--num')
grp
can contain any number of optionals, and one optional positional. I chose a different type
for the positional just a highlight the difference.
Just the positional value:
In [14]: parser.parse_args(['10'])
Out[14]: Namespace(num=None, pos=10)
Various forms of the optional:
In [16]: parser.parse_args(['-n10'])
Out[16]: Namespace(num='10', pos=0)
In [17]: parser.parse_args(['--num=10'])
Out[17]: Namespace(num='10', pos=0)
In [18]: parser.parse_args(['--num','10'])
Out[18]: Namespace(num='10', pos=0)
test the group exclusivity
In [25]: parser.parse_args(['--num=20','10'])
usage: ipython3 [-h] [-n NUM] [pos]
ipython3: error: argument pos: not allowed with argument -n/--num
and group required:
In [26]: parser.parse_args([])
usage: ipython3 [-h] [-n NUM] [pos]
ipython3: error: one of the arguments pos -n/--num is required
I experimented with giving the positional the same dest
as the optional - so both would write to num
. But this results in the positional over writing the dest
with its default (I can add details if needed)
In [19]: a.dest
Out[19]: 'pos'
In [20]: a.dest='num'
In [21]: parser.parse_args(['--num','10'])
Out[21]: Namespace(num=0)
Post parsing code will have to handle the args.pos
and args.num
values in what ever way makes sense.
The '-10
' input is impossible to handle. Well, I could define:
parser.add_argument('-1')
but the result is probably not what you want:
In [31]: parser.parse_args(['--num=20','-12'])
Out[31]: Namespace(1='2', num='20', pos=0)
Overall this requirement makes things unnecessarily difficult for you the programmer.