Один необязательный аргумент, который не требует позиционных аргументов - PullRequest
4 голосов
/ 30 июля 2011

У меня вопрос по поводу argparse в python: возможно ли иметь необязательный аргумент, который не требует позиционных аргументов?

Пример:

parser.add_argument('lat', help="latitude")
parser.add_argument('lon', help="longitude")
parser.add_argument('--method', help="calculation method (default: add)", default="add")
parser.add_argument('--list-methods', help="list available methods", action="store_true")

Обычная командная строка будет test.py 47.249 -33.282 или test.py 47.249 -33.282 --method sub. Но как только я вызываю скрипт с test.py --list-methods для получения списка всех доступных методов, я получаю error: to few arguments. Как я могу использовать argparse, чтобы иметь этот необязательный аргумент (--list-method), не имея позиционных аргументов (lat, lon)?

Ответы [ 3 ]

3 голосов
/ 20 сентября 2011
  • установите значение по умолчанию и nargs='?' для ваших позиционных аргументов
  • проверьте вручную в своем коде, что оба значения: широта и долгота был установлен, когда вы не находитесь в методах списка режиме

    parser = argparse.ArgumentParser()
    
    parser.add_argument('lat', help="latitude",default=None, nargs='?')
    parser.add_argument('lon', help="longitude",default=None, nargs='?')
    parser.add_argument('--method', help="calculation method (default: add)", default="add")
    parser.add_argument('--list-methods', help="list available methods", action="store_true")
    
    args = vars(parser.parse_args())
    
    if not args['list_methods'] and (args['lat'] == None or args['lon'] == None):
        print '%s: error: too few arguments' % sys.argv[0]
        exit(0)
    
    if args['list_methods']:
        print 'list methods here'
    else :
        print 'normal script execution'
    

, что дает:

$ test.py --list-method
перечислить методы здесь

$ test.py 4
test.py: ошибка: слишком мало аргументов

test.py 4 5
нормальное выполнение скрипта

1 голос
/ 27 июля 2013

Начиная с Python 3.3, parse_args проверяет свой набор seen_actions на набор требуемых действий и при необходимости выдает ошибку the following arguments are required....Ранее он проверил свой список оставшихся positionals и выдал сообщение об ошибке too few arguments.

Так что для более новых версий этот фрагмент должен делать то, что вы хотите:

parser = argparse.ArgumentParser()
lat=parser.add_argument('lat', help="latitude")
lon=parser.add_argument('lon', help="longitude")
parser.add_argument('--method', help="calculation method (default: add)", default="add")

class MyAction(argparse._StoreTrueAction):
    def __call__(self, parser, namespace, values, option_string=None):
        setattr(namespace, self.dest, self.const)
        lat.required = False
        lon.required = False

parser.add_argument('--list-methods', help="list available methods", action=MyAction)

Обычно lat и lon являются обязательными позиционерами, но если предпринято действие --list..., эти действия больше не требуются, и сообщение об ошибке не появляется, если они отсутствуют.


Другой способ настройкиargparse должен использовать несколько парсеров.В этом случае вы можете использовать один анализатор для проверки опции --list-methods, и в зависимости от того, что он получает, вызвать другой, который ищет позиционеры.

parser1 = argparse.ArgumentParser(add_help=False)
parser1.add_argument('--list-methods', help="list available methods", action='store_true')

parser2 = argparse.ArgumentParser()
parser2.add_argument('lat', help="latitude")
parser2.add_argument('lon', help="longitude")
parser2.add_argument('--method', help="calculation method (default: add)", default="add")
parser2.add_argument('--list-methods', help="list available methods", action='store_true')
def foo(argv):
    args,rest = parser1.parse_known_args(argv)
    if not args.list_methods:
        args = parser2.parse_args(argv)
    return args

parser2 отвечает на команду справки.parse_known_args разбирает, что может, и возвращает остаток в списке.parser2 также можно было бы написать, чтобы принять rest, args в качестве аргументов.

0 голосов
/ 30 июля 2011

Вы получаете error: to few arguments, потому что требуются lat и lon аргументы.

In [10]: parser.parse_args('--list-methods'.split())
ipython: error: too few arguments

, но

In [11]: parser.parse_args('--list-methods 10 20'.split())
Out[11]: Namespace(lat='10', list_methods=True, lon='20', method='add')

Вы должны сделать lat и lon аргументыпо желанию.

...