I have noticed that argparse
uses a rather "mystic" way of creating the variables in the parser. I know that the names of the variables are usually easy to infer:
it's the stripped version of long or short option (without the --
or -
respectively).
Also all hyphens (-
) becomes underscores (_
) to become legal variable names.
But that leaves me with a question about conflicting cases (I know it's an extreme case but the inferring part it's a bit mysterious to me). For example the program:
import argparse
parser = argparse.ArgumentParser(description="A simple test about var names")
parser.add_argument("--max-value", type=int, help="the maximum value", metavar="Maximum-value")
parser.add_argument("-m", "--max_value", action="store_true", help="Whether to the use maximum value", dest="max1")
args = parser.parse_args()
print("max_value {}".format(args.max1))
print("max-value {}".format(args.max_value))
uses apparently two very similar options (--max-value
and --max_value
) which lead to the same inferred variable max_value
. If either of the options was missing the variable would be max_value
without ambiguity.
But when both are present, apparently --max_value
gets the trophy variable max_value
and the second one (--max-value
) gets what? I haven't been able to find what's the second variable.
So, to access it I must define a variable explicitly with dest
option? How do I get list of the names of variables available? The funny thing is that if I use dest=
for the --max_value
option then --max-value
gets the expected variable max_value
while --max_value
gets the non inferred one (in my case max1
)!
I know also that metavar has nothing to do with the actual variable name but only affects the display in help.
Edit:
Adding some information from the @Martijn Pieters answer:
If I am getting it write if no dest
is applied the parser follows the general rule which states that an implicit dest
is applied. The same in my case dest="max_value"
.
So,
parser.add_argument("--max-value", type=int, help="the maximum value")
is exactly the same as:
parser.add_argument("--max-value", type=int, help="the maximum value", dest="max_value")
internally.
But, then the following code snippets should produce different results which it does not:
# parserv1.py
import argparse
parser = argparse.ArgumentParser(description="A simple test about var names")
parser.add_argument("-m", "--max_value", action="store_true", help="Whether to the use maximum value", dest="max_value")
parser.add_argument("--max-value", type=int, help="the maximum value", metavar="Maximum-value", dest="max_value")
args = parser.parse_args()
print("max-value {}".format(args.max_value))
>>>python parserv1.py -m --max-value 3
max-value 3
# parserv2.py
import argparse
parser = argparse.ArgumentParser(description="A simple test about var names")
parser.add_argument("--max-value", type=int, help="the maximum value", metavar="Maximum-value", dest="max_value")
parser.add_argument("-m", "--max_value", action="store_true", help="Whether to the use maximum value", dest="max_value")
args = parser.parse_args()
print("max-value {}".format(args.max_value))
>>>python parserv1.py -m --max-value 3
max-value 3
Both just print the value of max_value
as int
independently of the order they are declared.
So, int
option have higher precedence than binary (i.e. flags)? Are option types important in these cases?
P.S. I am using python 3.6.3 and since it might be a version issue I wanted to mention it.
After importing the library, argparse. ArgumentParser() initializes the parser so that you can start to add custom arguments. To add your arguments, use parser. add_argument() .
dest is equal to the first argument supplied to the add_argument() function, as illustrated. The second argument, radius_circle , is optional. A long option string --radius supplied to the add_argument() function is used as dest , as illustrated.
Number of Arguments If you want your parameters to accept a list of items you can specify nargs=n for how many arguments to accept. Note, if you set nargs=1 , it will return as a list not a single value.
Using argparse is how you let the user of your program provide values for variables at runtime. It's a means of communication between the writer of a program and the user. That user might be your future self. 😃 Using argparse means the doesn't need to go into the code and make changes to the script.
There is no conflict here; for both --max-value
and --max_value
, the library simply generates the exact same destination name. Multiple options writing to the same dest
destination name is perfectly valid; the last option used on the command line wins in that case:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument("--option1", dest="foo")
_StoreAction(option_strings=['--option1'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument("--option2", dest="foo")
_StoreAction(option_strings=['--option2'], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args(['--option2', 'bar', '--option1', 'baz'])
Namespace(foo='baz')
Here --option1 baz
wins because --option1
was used last on the command line.
Note that any defaults are applied before command-line parsing; the first registered option default value wins. Then the command-line is parsed and if only one of the options is used, then naturally the action associated with that option wins.
It is up to you to pick non-conflicting destination names. Not picking option strings that are easy to confuse is also a good idea.
If you were looking for a formal set of rules on what dest
name is generated for a given optional argument, see the dest
option documenation:
For optional argument actions, the value of
dest
is normally inferred from the option strings.ArgumentParser
generates the value of dest by taking the first long option string and stripping away the initial--
string. If no long option strings were supplied,dest
will be derived from the first short option string by stripping the initial-
character. Any internal-
characters will be converted to_
characters to make sure the string is a valid attribute name.
Multiple options all writing to the same dest
destination name is useful for supporting old, deprecated names for a given option:
parser.add_argument('-n', '--new', dest='new', help="New hotness option")
# old name for the new hotness option, now deprecated but still supported
# argparse.SUPPRESS ensures it is no longer listed in the help output
parser.add_argument('-o', '--old', dest='new', help=argparse.SUPPRESS)
So using -o
or --old
on the command line has the exact same effect as using -n
or --new
; the same destination name is set on the namespace.
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