I'm trying to enable a user to pass in a function name. For some reason it seems that argparse performs the type check/conversion BEFORE it checks the choices. Is this a bug? Best thing to do?
import argparse
def foo():
return 'foo'
def bar():
return 'bar'
parser = argparse.ArgumentParser()
functions = {f.__name__:f for f in [foo, bar]}
parser.add_argument("function", type=lambda f: functions.get(f), help="which function", choices=functions)
args = parser.parse_args()
print(args.function())
This throws:
$ python blah.py foo
usage: blah.py [-h] {foo,bar}
blah.py: error: argument function: invalid choice: <function foo at 0x7f65746dd848> (choose from 'foo', 'bar')
parse_args() returns two values: options , an object containing values for all of your options—e.g. if --file takes a single string argument, then options. file will be the filename supplied by the user, or None if the user did not supply that option.
After importing the library, argparse. ArgumentParser() initializes the parser so that you can start to add custom arguments. To add your arguments, use parser.
Python argparse optional argument These are optional arguments. The module is imported. An argument is added with add_argument . The action set to store_true will store the argument as True , if present.
Yes, during parsing the type
then choices
order is clear and intentional (and not just incidental). When preparing to assign arg_strings
to the namespace
it calls _get_values
, which does:
def _get_values(self, action, arg_strings)
.... (various nargs tests)
value = self._get_value(action, arg_string)
self._check_value(action, value)
return value
where _get_value
applies the action.type
function, and _check_value
tests
value not in action.choices
For parsing choices
only has to respond to the in
(__contains__
) expression.
So choices
have to reflect values after conversion. If type
is int
, then choices=[1,2,3]
is correct, ['1','2','3']
is not.
There are some (largely unresolved) bug issues over the display of the choices. Long lists, e.g. range(100)
work in parsing, but don't display nicely. And display also requires that choices
be iterable (e.g. a list, tuple, dictionary). This display issue affects the usage, the help and the error messages (each formats choices
slightly differently).
metavar
is your most powerful tool for replacing an undesirable choices
list. I'd have to run a test case to see whether it solves things for all 3 situations.
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