作为选项传递列表的argparse选项

我试图将一个列表作为parameter passing给命令行程序。 有一个argparse选项作为选项传递一个列表?

  parser.add_argument('-l', '--list', type=list, action='store', dest='list', help='<Required> Set flag', required=True) 

脚本如下所示

 python test.py -l "265340 268738 270774 270817" 

TL; DR

使用nargs选项或nargs选项的'append'设置(取决于用户界面的行为方式)。

NARGS

 parser.add_argument('-l','--list', nargs='+', help='<Required> Set flag', required=True) # Use like: # python arg.py -l 1234 2345 3456 4567 

nargs='+'需要一个或多个参数, nargs='*'需要零个或更多。

附加

 parser.add_argument('-l','--list', action='append', help='<Required> Set flag', required=True) # Use like: # python arg.py -l 1234 -l 2345 -l 3456 -l 4567 

随着append你提供了多个选项来build立列表。

不要使用type=list !!! – 可能没有你想用type=listargparse 。 永远。


让我们来看看更多的细节,可以尝试一些不同的方法,最终的结果。

 import argparse parser = argparse.ArgumentParser() # By default it will fail with multiple arguments. parser.add_argument('--default') # Telling the type to be a list will also fail for multiple arguments, # but give incorrect results for a single argument. parser.add_argument('--list-type', type=list) # This will allow you to provide multiple arguments, but you will get # a list of lists which is not desired. parser.add_argument('--list-type-nargs', type=list, nargs='+') # This is the correct way to handle accepting multiple arguments. # '+' == 1 or more. # '*' == 0 or more. # '?' == 0 or 1. # An int is an explicit number of arguments to accept. parser.add_argument('--nargs', nargs='+') # To make the input integers parser.add_argument('--nargs-int-type', nargs='+', type=int) # An alternate way to accept multiple inputs, but you must # provide the flag once per input. Of course, you can use # type=int here if you want. parser.add_argument('--append-action', action='append') # To show the results of the given option to screen. for _, value in parser.parse_args()._get_kwargs(): if value is not None: print(value) 

这是您可以预期的输出:

 $ python arg.py --default 1234 2345 3456 4567 ... arg.py: error: unrecognized arguments: 2345 3456 4567 $ python arg.py --list-type 1234 2345 3456 4567 ... arg.py: error: unrecognized arguments: 2345 3456 4567 $ # Quotes won't help here... $ python arg.py --list-type "1234 2345 3456 4567" ['1', '2', '3', '4', ' ', '2', '3', '4', '5', ' ', '3', '4', '5', '6', ' ', '4', '5', '6', '7'] $ python arg.py --list-type-nargs 1234 2345 3456 4567 [['1', '2', '3', '4'], ['2', '3', '4', '5'], ['3', '4', '5', '6'], ['4', '5', '6', '7']] $ python arg.py --nargs 1234 2345 3456 4567 ['1234', '2345', '3456', '4567'] $ python arg.py --nargs-int-type 1234 2345 3456 4567 [1234, 2345, 3456, 4567] $ # Negative numbers are handled perfectly fine out of the box. $ python arg.py --nargs-int-type -1234 2345 -3456 4567 [-1234, 2345, -3456, 4567] $ python arg.py --append-action 1234 --append-action 2345 --append-action 3456 --append-action 4567 ['1234', '2345', '3456', '4567'] 

外套

  • 使用nargsaction='append'
    • 从用户的angular度来说, nargs可以更直接,但是如果存在位置参数,那么它可能是不直观的,因为argparse不能说出什么是位置参数和属于nargs 。 如果你有位置参数,那么action='append'可能最终成为更好的select。
    • 以上只有在给出'*''+''?'情况下才是正确'?' 。 如果你提供了一个整数(比如4 ),那么混合选项和nargs以及位置参数都没有问题,因为argparse会准确的知道这个选项有多less值。
  • 不要在命令行中使用引号1
  • 不要使用type=list ,因为它会返回一个列表的列表
    • 发生这种情况是因为在这种情况下, argparse使用type的值来强制每个给定的参数为你select的type ,而不是所有参数的聚合。
    • 您可以使用type=int (或其他)来获取整数列表(或其他)

1 :我不是一般的意思..我的意思是使用引号传递一个列表argparse是不是你想要的。

我更喜欢传递一个分隔的string,我稍后在脚本中parsing。 原因是这样的; 该列表可以是任何types的intstr ,有时使用nargs我会遇到问题,如果有多个可选参数和位置参数。

 parser = ArgumentParser() parser.add_argument('-l', '--list', help='delimited list input', type=str) args = parser.parse_args() my_list = [int(item) for item in args.list.split(',')] 

然后,

 python test.py -l "265340,268738,270774,270817" [other arguments] 

要么,

 python test.py -l 265340,268738,270774,270817 [other arguments] 

将工作正常。 分隔符也可以是一个空格,它可以通过在参数值周围加上引号,就像问题中的例子一样。

除了nargs ,如果您事先知道该列表,则可能需要使用choices

 >>> parser = argparse.ArgumentParser(prog='game.py') >>> parser.add_argument('move', choices=['rock', 'paper', 'scissors']) >>> parser.parse_args(['rock']) Namespace(move='rock') >>> parser.parse_args(['fire']) usage: game.py [-h] {rock,paper,scissors} game.py: error: argument move: invalid choice: 'fire' (choose from 'rock', 'paper', 'scissors') 

如果你打算让一个开关取多个参数,那么你使用nargs='+' 。 如果你的例子'-l'实际上是整数:

 a = argparse.ArgumentParser() a.add_argument( '-l', '--list', # either of this switches nargs='+', # one or more parameters to this switch type=int, # /parameters/ are ints dest='list', # store in 'list'. default=[], # since we're not specifying required. ) print a.parse_args("-l 123 234 345 456".split(' ')) print a.parse_args("-l 123 -l=234 -l345 --list 456".split(' ')) 

产生

 Namespace(list=[123, 234, 345, 456]) Namespace(list=[456]) # Attention! 

如果多次指定相同的参数,则默认操作( 'store' )会replace现有数据。

另一种方法是使用append动作:

 a = argparse.ArgumentParser() a.add_argument( '-l', '--list', # either of this switches type=int, # /parameters/ are ints dest='list', # store in 'list'. default=[], # since we're not specifying required. action='append', # add to the list instead of replacing it ) print a.parse_args("-l 123 -l=234 -l345 --list 456".split(' ')) 

哪个产生

 Namespace(list=[123, 234, 345, 456]) 

或者你可以写一个自定义的处理程序/操作来parsing逗号分隔的值,以便你可以做到

 -l 123,234,345 -l 456 

在argparse的add_argument方法中使用nargs参数

我使用nargs =' 作为add_argument参数。 如果我不传递任何明确的参数, 我特别使用nargs =' '来select默认值

以代码片段为例:

例如:temp_args1.py

请注意:下面的示例代码是用python3编写的。 通过改变打印语句格式,可以运行在python2中

  #!/usr/local/bin/python3.6 from argparse import ArgumentParser description = 'testing for passing multiple arguments and to get list of args' parser = ArgumentParser(description=description) parser.add_argument('-i', '--item', action='store', dest='alist', type=str, nargs='*', default=['item1', 'item2', 'item3'], help="Examples: -i item1 item2, -i item3") opts = parser.parse_args() print("List of items: {}".format(opts.alist)) 

注意:我正在收集存储在列表中的多个string参数 – opts.alist如果需要整数列表,请将parser.add_argument上的types参数更改为int

执行结果:

  python3.6 temp_agrs1.py -i item5 item6 item7 List of items: ['item5', 'item6', 'item7'] python3.6 temp_agrs1.py -i item10 List of items: ['item10'] python3.6 temp_agrs1.py List of items: ['item1', 'item2', 'item3'] 

add_argument()type只是一个add_argument()对象,它接收string并返回选项值。

 import ast def arg_as_list(s): v = ast.literal_eval(s) if type(v) is not list: raise argparse.ArgumentTypeError("Argument \"%s\" is not a list" % (s)) return v def foo(): parser.add_argument("--list", type=arg_as_list, default=[], help="List of values") 

这将允许:

 $ ./tool --list "[1,2,3,4]"