Как изменить метавар для позиционного аргумента в 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
на аргумент position range1
, argparse не может обрабатывать кортеж параметра metavar
(ValueError: too many values to unpack
).
Единственный способ, которым я смог его запустить, - это сделать -range2
. Но тогда сообщение справки далеко не так хорошо, как для случая -range1
.
Есть ли способ получить то же справочное сообщение, что и для случая -range1
, но для позиционного аргумента вместо необязательного?
Ответы
Ответ 1
Как насчет:
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
Ответ 2
Однако, если я изменяю необязательный аргумент -range1 на аргумент positional 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 отдельных позиций, вероятно, имеет в виду дизайнеры argpse.
Эта проблема была поднята (но не исправлена)
http://bugs.python.org/issue14074
"argparse позволяет nargs > 1 для позиционных аргументов, но не позволяет метавару быть кортежем"