argparse: let the same required argument be positional OR optional
<p>I would like to have a required command line argument passed as a positional argument or an optional argument. For example, I would like the same action be performed from any of the following invocations:</p>

<pre><code>prog 10
prog -10
prog -n 10
prog --num 10
</code></pre>

<p>Is this possible with argparse?</p>

<p>With a mutually exclusive group I can create a reasonable approximation:</p>

<p>In an interactive session:</p>

<pre><code>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')
</code></pre>

<p><code>grp</code> can contain any number of optionals, and one optional positional.  I chose a different <code>type</code> for the positional just a highlight the difference.</p>

<p>Just the positional value:</p>

<pre><code>In [14]: parser.parse_args(['10'])
Out[14]: Namespace(num=None, pos=10)
</code></pre>

<p>Various forms of the optional:</p>

<pre><code>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)
</code></pre>

<p>test the group exclusivity</p>

<pre><code>In [25]: parser.parse_args(['--num=20','10'])
usage: ipython3 [-h] [-n NUM] [pos]
ipython3: error: argument pos: not allowed with argument -n/--num
</code></pre>

<p>and group required:</p>

<pre><code>In [26]: parser.parse_args([])
usage: ipython3 [-h] [-n NUM] [pos]
ipython3: error: one of the arguments pos -n/--num is required
</code></pre>

<p>I experimented with giving the positional the same <code>dest</code> as the optional - so both would write to <code>num</code>.  But this results in the positional over writing the <code>dest</code> with its default (I can add details if needed)</p>

<pre><code>In [19]: a.dest
Out[19]: 'pos'
In [20]: a.dest='num'
In [21]: parser.parse_args(['--num','10'])
Out[21]: Namespace(num=0)
</code></pre>

<p>Post parsing code will have to handle the <code>args.pos</code> and <code>args.num</code> values in what ever way makes sense.</p>

<p>The <code>'-10</code>' input is impossible to handle.  Well, I could define:</p>

<pre><code>parser.add_argument('-1')
</code></pre>

<p>but the result is probably not what you want:</p>

<pre><code>In [31]: parser.parse_args(['--num=20','-12'])
Out[31]: Namespace(1='2', num='20', pos=0)
</code></pre>

<p>Overall this requirement makes things unnecessarily difficult for you the programmer.</p>

python argparse