Как изменить метавар для позиционного аргумента в argparse питонов? - PullRequest
13 голосов
/ 31 октября 2011

В пакете 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, но для позиционного аргумента вместоопционально

Ответы [ 2 ]

7 голосов
/ 31 октября 2011

Как насчет:

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
5 голосов
/ 26 июля 2013

Однако, если я изменю необязательный аргумент -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 о трех отдельных позициях, вероятно, было задумано дизайнерами argparse.

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

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

...