Как изменить метавар для позиционного аргумента в pythons argparse?

В пакете argparse параметр metavar изменяет отображаемое справочное сообщение программы. Следующая программа не предназначена для работы, она просто используется для демонстрации поведения параметра metavar.

import argparse
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description = "Print a range.")

    parser.add_argument("-range1", nargs = 3, type = int, help = "Specify range with: start, stop, step.", metavar = ("start", "stop", "step"))
    parser.add_argument("-range2", nargs = 3, type = int, help = "Specify range with: start, stop, step.", metavar = "r2")

Соответствующее справочное сообщение:

usage: main.py [-h] [-range1 start stop step] [-range2 r2 r2 r2]

Print a range.

optional arguments:
  -h, --help            show this help message and exit
  -range1 start stop step
                        Specify range with: start, stop, step.
  -range2 r2 r2 r2      Specify range with: start, stop, step.

Обратите внимание на различия между -range1 и -range2. Ясно, что -range1 является предпочтительным способом справочного сообщения.

До этого момента мне все ясно. Однако если я заменю необязательный аргумент -range1 на позиционный аргумент range1, argparse не сможет работать с кортежем параметра metavar (ValueError: too many values to unpack).
Единственный способ, которым я смог заставить его работать, был так, как это делается -range2. Но тогда справочное сообщение далеко не так хорошо, как для случая -range1.

Есть ли способ получить то же справочное сообщение, что и для случая -range1, но для позиционного аргумента вместо необязательного?


person Woltan    schedule 31.10.2011    source источник


Ответы (2)


Как насчет:

import argparse
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description = "Print a range.")

    parser.add_argument("start", type = int, help = "Specify start.", )
    parser.add_argument("stop", type = int, help = "Specify stop.", )
    parser.add_argument("step", type = int, help = "Specify step.", )

    args=parser.parse_args()
    print(args)

который дает

% test.py -h
usage: test.py [-h] start stop step

Print a range.

positional arguments:
  start       Specify start.
  stop        Specify stop.
  step        Specify step.

optional arguments:
  -h, --help  show this help message and exit
person unutbu    schedule 31.10.2011
comment
Привет unutbu, я думаю, что я реализую это, как вы предложили. Однако мне кажется, что связь между этими тремя параметрами может быть не столь очевидной, как если бы они были сгруппированы в один параметр. - person Woltan; 03.11.2011
comment
Я понимаю что ты имеешь ввиду. Ну, вы могли бы добавить больше пояснений, например description='''Prints a range. %(prog)s start stop step prints start, start+step, start+2*step, ..., start+n*step where n is the greatest integer such that start+n*stop<stop. For example, %(prog)s 1 4 2 prints...''' - person unutbu; 03.11.2011

Однако если я изменю необязательный аргумент -range1 на позиционный аргумент range1, argparse не сможет работать с кортежем параметра metavar (ValueError: слишком много значений для распаковки).

argparse не должен выдавать это сообщение об ошибке too many values to unpack. Это произведено metavar, = self._metavar_formatter(action, default)(1). Обычно эта функция создает один список элементов или кортеж, но в вашем случае она возвращает метавар кортежа. Он должен дать более информативное сообщение об ошибке (tuple metavar not allowed with positionals ?) или изящно адаптировать метавар (start|stop|step ?). Другой вариант — использовать метавар по умолчанию в строке справки вместо кортежа.

Метавар кортежа работает нормально в строке использования.

Я думаю, что форматирование справки было написано с учетом унифицированных позиций. В строке использования может отображаться X [X [X ...]], но в строке справки просто X ... description of X.

Ваши 3 элемента имеют разные имена, поэтому предложение unutbu о 3 отдельных позициях, вероятно, имелось в виду дизайнерами argparse.

Эта проблема была поднята (но не исправлена)

http://bugs.python.org/issue14074 "argparse допускает nargs>1 для позиционных аргументов, но не не разрешать metavar быть кортежем"

person hpaulj    schedule 26.07.2013