The title pretty much says it all. If I have nargs greater than 1, is there any way I can set restrictions (such as choice/type) on the individual args parsed?
This is some example code:
parser = argparse.ArgumentParser()
parser.add_argument('-c', '--credits', nargs=2,
help='number of credits required for a subject')
For the -c argument I need to specify a subject and how many credits are required. The subject should be limited to a predefined list of subjects, and the number of credits required should be a float.
I could probably do this with a subparser, but as it is this is already part of a sub-command so I don't really want things to get any more complicated.
You can validate it with a custom action:
import argparse
import collections
class ValidateCredits(argparse.Action):
def __call__(self, parser, args, values, option_string=None):
# print '{n} {v} {o}'.format(n=args, v=values, o=option_string)
valid_subjects = ('foo', 'bar')
subject, credits = values
if subject not in valid_subjects:
raise ValueError('invalid subject {s!r}'.format(s=subject))
credits = float(credits)
Credits = collections.namedtuple('Credits', 'subject required')
setattr(args, self.dest, Credits(subject, credits))
parser = argparse.ArgumentParser()
parser.add_argument('-c', '--credits', nargs=2, action=ValidateCredits,
help='subject followed by number of credits required',
metavar=('SUBJECT', 'CREDITS')
)
args = parser.parse_args()
print(args)
print(args.credits.subject)
print(args.credits.required)
For example,
% test.py -c foo 2
Namespace(credits=Credits(subject='foo', required=2.0))
foo
2.0
% test.py -c baz 2
ValueError: invalid subject 'baz'
% test.py -c foo bar
ValueError: could not convert string to float: bar
Side note, because this question turns up when searching for "argparse nargs choices":
A custom action is only needed if the nargs arguments require a heterogenous type validation, ie, the argument at index 0 should be a different type (here: limited type of subjects) than the argument at index 1 (here: float) etc.
If a homogenous type validation is desired, it is sufficient to combine nargs
with choices
directly. For instance:
parser.add_argument(
"--list-of-xs-or-ys",
nargs="*",
choices=["x", "y"],
)
would allow anything like --list-of-xs-or-ys xyxy
, but would complain if the user specifies anything else than x
or y
.
A caller of a Action class only catch a ArgumentError.
https://github.com/python/cpython/blob/3.8/Lib/argparse.py#L1805
For expecting to catch an exception by a caller, You should raise as following in your custom action.
raise ArgumentError(self, 'invalid subject {s!r}'.format(s=subject))
i suppose you could try this - in add_argument(), you can specify a limited set of inputs with choice='xyz' or choice=[this, that] as described here: http://docs.python.org/library/argparse.html#choices
parser = argparse.ArgumentParser()
parser.add_argument('-c', '--credits', choice='abcde', nargs=2,
help='number of credits required for a subject')
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.