The whole point to defining choices is to make the parser complain about values that are not in the list. But there are some alternatives:
omit choices (include them in the help text if you want), and do your own testing after parsing. argparse
doesn't have to do everything for you. It's main purpose is to figure out what your user wants.
redefine the parser.error
method (via subclassing is best) to redirect the error from sys.exit
. But you'll have to parse the error message to distinguish between this error and other ones that the parser might raise.
define a type
function that checks for choices, and makes the default substitution.
The parsing of the '--compiler' option goes something like this:
- grab the string argument after the
--compiler
flag
- pass it through the
type
function. Default is lambda x:x
. int
converts it to integer, etc. Raise ValueError
is value is bad.
- check the returned value against the
choices
list (if any)
- use the
action
to add the value to the Namespace (default simply stores it).
Error in any of these steps produces an ArgumentError
which is trapped by the parser.error
method and passed to a parser.exit
method.
Since the store_action
occurs after type
and choices
checking, a custom action won't bypass their errors.
Here's a possible type
solution (not tested)
def compile_choices(astr):
if astr in ['default', 'clang3.4', 'clang3.5']:
return astr
else:
return 'default'
# could raise ValueError('bad value') if there are some strings you don't like
argp.add_argument('--compiler', type=compile_choices)
=================
If compile_choices
takes other arguments, such as the list of choices or the default, you'll need to wrap in some why that defines those values before parsing.
An example accepting a binary string representation:
parser.add_argument('--binary', type=lambda x: int(x, base=2),
help='integer in binary format', default='1010')
or
parser.add_argument('--binary', type=functools.partial(int, base=2), default='1010')