在Python的argparse中多次使用相同的选项

Joh*_*ard 59 python argparse multiple-arguments

我正在尝试编写一个接受多个输入源的脚本,并对每个源做一些事情.像这样的东西

./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
Run Code Online (Sandbox Code Playgroud)

但我无法弄清楚如何使用它argparse.它似乎设置为每个选项标志只能使用一次.我知道如何将多个参数与单个选项(nargs='*'nargs='+')相关联,但仍然不允许我-i多次使用该标志.我该如何完成这项工作?

为了清楚起见,我最终想要的是一系列字符串列表.所以

[["input1_url", "input1_name", "input1_other"],
 ["input2_url", "input2_name", "input2_other"],
 ["input3_url", "input3_name"]]
Run Code Online (Sandbox Code Playgroud)

hpa*_*ulj 71

这是一个解析器,它处理重复的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']])
Run Code Online (Sandbox Code Playgroud)

这不处理这种2 or 3 argument情况(虽然我前段时间为一个处理这样一个范围的Python bug /问题编写了一个补丁).

如何使用nargs=3和单独的参数定义metavar=('url','name','other')

元组metavar也可以nargs='+'nargs='*'; 2个字符串用作[-u A [B ...]][-u [A [B ...]]].


Ami*_*mir 19

这很简单; 只需添加action='append'nargs='*'(或'+').

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-i', action='append', nargs='+')
args = parser.parse_args()
Run Code Online (Sandbox Code Playgroud)

然后,当你运行它,你得到

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']]
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,正是我需要的!:D 旁注:可能的默认值需要是类型列表/数组,否则 Argparse 将失败 (5认同)

She*_*zan 18

在此线程中添加其他。

\n

如果您使用action=\'append\'add_argument()那么,每次添加选项时,您都会在列表中的列表中获得参数。

\n

如你所愿:

\n
[\n   ["input1_url", "input1_name", "input1_other"],\n   ["input2_url", "input2_name", "input2_other"],\n   ["input3_url", "input3_name"]\n]\n
Run Code Online (Sandbox Code Playgroud)\n

但如果有人想要将这些参数放在同一个 中list[],请在代码中使用action=\'extend\'\xc2\xa0 代替。action=\'append\'这将在一个列表中为您提供这些参数。

\n
[\n  "input1_url", \n  "input1_name", \n  "input1_other", \n  "input2_url", \n  "input2_name", \n  "input2_other", \n  "input3_url", \n  "input3_name"\n]\n
Run Code Online (Sandbox Code Playgroud)\n

  • 你的答案在底部,但我正在寻找这个“扩展”位:)谢谢! (2认同)

che*_*ner 17

-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']])
Run Code Online (Sandbox Code Playgroud)

要处理可选值,您可以尝试使用简单的自定义类型.在这种情况下,参数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']])
Run Code Online (Sandbox Code Playgroud)

要获得更多控制,请定义自定义操作.这个扩展了内置_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)
Run Code Online (Sandbox Code Playgroud)

  • 这不是*完全*做你想要的; 我错过了`inputX_other_var`是可选的. (2认同)