Я пытаюсь написать сценарий, который принимает несколько источников ввода и что-то делает с каждым из них. Что-то вроде этого
./my_script.py \
-i input1_url input1_name input1_other_var \
-i input2_url input2_name input2_other_var \
-i input3_url input3_name
# notice inputX_other_var is optional
Но я не совсем понимаю, как это сделать с помощью argparse
. Кажется, что он настроен так, что каждый флаг опции может использоваться только один раз. Я знаю, как связать несколько аргументов с одним параметром ( nargs='*'
или nargs='+'
), но это все равно не позволяет мне использовать -i
флаг несколько раз. Как мне это сделать?
Чтобы быть ясным, в конце я хотел бы получить список списков строк. Так
[["input1_url", "input1_name", "input1_other"],
["input2_url", "input2_name", "input2_other"],
["input3_url", "input3_name"]]
python
argparse
multiple-arguments
Джон Аллард
источник
источник
Ответы:
Вот парсер, который обрабатывает повторяющиеся 2 необязательных аргумента - с именами, определенными в
metavar
:parser=argparse.ArgumentParser() parser.add_argument('-i','--input',action='append',nargs=2, metavar=('url','name'),help='help:') In [295]: parser.print_help() usage: ipython2.7 [-h] [-i url name] optional arguments: -h, --help show this help message and exit -i url name, --input url name help: In [296]: parser.parse_args('-i one two -i three four'.split()) Out[296]: Namespace(input=[['one', 'two'], ['three', 'four']])
Это не относится к
2 or 3 argument
случаю (хотя некоторое время назад я написал патч для ошибки / проблемы Python, которая могла бы обрабатывать такой диапазон).Как насчет отдельного определения аргумента с помощью
nargs=3
иmetavar=('url','name','other')
?Кортеж
metavar
также можно использовать сnargs='+'
иnargs='*'
; две строки используются как[-u A [B ...]]
или[-u [A [B ...]]]
.источник
Это просто; просто добавьте оба
action='append'
иnargs='*'
(или'+'
).import argparse parser = argparse.ArgumentParser() parser.add_argument('-i', action='append', nargs='+') args = parser.parse_args()
Затем, когда вы запустите его, вы получите
In [32]: run test.py -i input1_url input1_name input1_other_var -i input2_url i ...: nput2_name input2_other_var -i input3_url input3_name In [33]: args.i Out[33]: [['input1_url', 'input1_name', 'input1_other_var'], ['input2_url', 'input2_name', 'input2_other_var'], ['input3_url', 'input3_name']]
источник
-i
должен быть настроен на прием 3 аргументов и использованиеappend
действия.>>> p = argparse.ArgumentParser() >>> p.add_argument("-i", nargs=3, action='append') _AppendAction(...) >>> p.parse_args("-i a b c -i d e f -i g h i".split()) Namespace(i=[['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']])
Для обработки необязательного значения вы можете попробовать использовать простой настраиваемый тип. В этом случае аргумент to
-i
представляет собой одну строку с разделителями-запятыми, с числом разделений, ограниченным до 2. Вам потребуется постобработка значений, чтобы убедиться, что указаны как минимум два значения.>>> p.add_argument("-i", type=lambda x: x.split(",", 2), action='append') >>> print p.parse_args("-i a,b,c -i d,e -i g,h,i,j".split()) Namespace(i=[['a', 'b', 'c'], ['d', 'e'], ['g', 'h', 'i,j']])
Для большего контроля определите настраиваемое действие. Этот расширяет встроенный
_AppendAction
(используемыйaction='append'
), но просто проверяет некоторый диапазон количества переданных аргументов-i
.class TwoOrThree(argparse._AppendAction): def __call__(self, parser, namespace, values, option_string=None): if not (2 <= len(values) <= 3): raise argparse.ArgumentError(self, "%s takes 2 or 3 values, %d given" % (option_string, len(values))) super(TwoOrThree, self).__call__(parser, namespace, values, option_string) p.add_argument("-i", nargs='+', action=TwoOrThree)
источник
inputX_other_var
необязательно.