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
destis normally inferred from the option strings.ArgumentParsergenerates the value of dest by taking the first long option string and stripping away the initial--string. If no long option strings were supplied,destwill 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