Python argparse type and choice restrictions with nargs > 1

后端 未结 4 2087
自闭症患者
自闭症患者 2020-12-30 02:09

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

相关标签:
4条回答
  • 2020-12-30 02:23

    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, i.e., the argument at index 0 should be a different type (here: limited type of subjects) then 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 x y x y, but would complain if the user specifies anything else then x or y.

    0 讨论(0)
  • 2020-12-30 02:29

    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))

    0 讨论(0)
  • 2020-12-30 02:30

    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
    
    0 讨论(0)
  • 2020-12-30 02:34

    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')
    
    0 讨论(0)
提交回复
热议问题