Python argparse: есть ли способ указать диапазон в nargs?

У меня есть необязательный аргумент, который поддерживает сам список аргументов.

Я имею в виду, что он должен поддерживать:

  • -f 1 2
  • -f 1 2 3

но нет:

  • -f 1
  • -f 1 2 3 4

Есть ли способ заставить это в argparse ? Теперь я использую nargs="*", а затем проверяю длину списка.

Изменить: В соответствии с просьбой, мне нужна была возможность определить диапазон допустимого количества аргументов. Я имею в виду, что сказать (в примере) 2 или 3 аргумента правильно, но не 1 или 4 или что-то еще, что не входит в диапазон 2..3


person Doppelganger    schedule 16.11.2010    source источник
comment
Я не понимаю. Вы имеете в виду, что хотите иметь возможность поддерживать, например. от одного до десяти аргументов?   -  person Katriel    schedule 16.11.2010
comment
Не могли бы вы подробнее рассказать о правилах? Вы хотите требовать не менее 2 и не более 3 значений? Они должны быть 1-4 или они могут быть любыми?   -  person slf    schedule 16.11.2010


Ответы (1)


Это можно сделать с помощью пользовательского действия:

import argparse

def required_length(nmin,nmax):
    class RequiredLength(argparse.Action):
        def __call__(self, parser, args, values, option_string=None):
            if not nmin<=len(values)<=nmax:
                msg='argument "{f}" requires between {nmin} and {nmax} arguments'.format(
                    f=self.dest,nmin=nmin,nmax=nmax)
                raise argparse.ArgumentTypeError(msg)
            setattr(args, self.dest, values)
    return RequiredLength

parser=argparse.ArgumentParser(prog='PROG')
parser.add_argument('-f', nargs='+', action=required_length(2,3))

args=parser.parse_args('-f 1 2 3'.split())
print(args.f)
# ['1', '2', '3']

try:
    args=parser.parse_args('-f 1 2 3 4'.split())
    print(args)
except argparse.ArgumentTypeError as err:
    print(err)
# argument "f" requires between 2 and 3 arguments
person unutbu    schedule 16.11.2010
comment
Путешественник во времени здесь. Отличный ответ! Однако здесь вы создаете подкласс argparse.Action... что произойдет, если я хочу, чтобы мое действие было append? Как я могу изменить этот код, чтобы добавить несколько экземпляров этого аргумента, а также получить указанный эффект диапазона? - person 2rs2ts; 09.07.2013
comment
Ах, на самом деле, объединение вашего кода с этим ответом сделало то, что я искал. Не обращайте на меня внимания - если только вы не думали о том же, в этом случае проверьте этот ответ. - person 2rs2ts; 09.07.2013
comment
Предлагается патч bugs.python.org/issue11354 для добавления параметра диапазона nargs, например. nargs=(2,3) или nargs='{2,3}' (обозначение стиля re). Этот подход более эффективен, когда другие позиционные значения имеют переменные значения nargs. В противном случае этот подход с пользовательскими действиями работает нормально. - person hpaulj; 01.08.2013
comment
Это 2018 год, и он все еще находится на рассмотрении патча. - person huggie; 31.08.2018
comment
Почти 2019 год и все еще на рассмотрении. Простым решением для добавления (но очень грязным) было бы расширение argparse._AppendAction и использование super.__call__() в конце вашего метода вызова. - person Mad Physicist; 31.12.2018
comment
Сейчас 2020 год, и он был закрыт, потому что мало кто этого хочет. - person Gavin S. Yancey; 14.01.2020