我试图将一个列表作为参数传递给命令行程序。是否有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"

当前回答

除了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')

其他回答

我更喜欢传递一个带分隔符的字符串,稍后在脚本中解析。原因是;列表可以是任何类型的int或str,有时使用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]

or,

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

会很好。分隔符也可以是空格,这将强制在参数值周围加上引号,就像问题中的示例一样。

或者你也可以使用Chepner评论中建议的lambda类型:

parser.add_argument('-l', '--list', help='delimited list input', 
    type=lambda s: [int(item) for item in s.split(',')])

请注意,如果你传递action='append'和默认参数,Argparse将尝试附加到提供的默认值,而不是替换默认值,这可能是你所期望的,也可能不是。

下面是Argparse Docs中给出的一个action='append示例。 在这种情况下,事情将如预期的那样工作:

>> import argparse
>> parser = argparse.ArgumentParser()
>> parser.add_argument('--foo', action='append')
>> parser.parse_args('--foo 1 --foo 2'.split())

Out[2]: Namespace(foo=['1', '2'])

然而,如果你选择提供一个默认值,Argparse的"append"操作将尝试附加到提供的默认值,而不是替换默认值:

import argparse
REASONABLE_DEFAULTS = ['3', '4']
parser = argparse.ArgumentParser()
parser.add_argument('--foo', default=REASONABLE_DEFAULTS,action='append')
parser.parse_args('--foo 1 --foo 2'.split())

Out[6]: Namespace(foo=['3', '4', '1', '2'])

如果你希望Argparse替换默认值——比如传入一个元组作为默认值,而不是一个列表——这可能会导致一些令人困惑的错误:

import argparse
REASONABLE_DEFAULTS = ('3', '4')
parser = argparse.ArgumentParser()
parser.add_argument('--foo', default=REASONABLE_DEFAULTS,action='append')
parser.parse_args('--foo 1 --foo 2'.split())

AttributeError: 'tuple' object has no attribute 'append'

有一个跟踪这种意外行为的bug,但由于它可以追溯到2012年,所以不太可能得到解决。

编辑:结合了Katu建议的改进,删除了单独的解析步骤。

JSON列表解决方案

通过命令行处理传递列表(也包括字典)的一个好方法是使用json。

# parse_list.py
import argparse
import json

parser = argparse.ArgumentParser()
# note type arg, used to load json string
parser.add_argument('-l', '--list', type=json.loads)
args = parser.parse_args()
print(args.list)

示例使用

$ python parse_list.py -l "[265340, 268738, 270774, 270817]"
[265340, 268738, 270774, 270817]

除了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='lst',      # store in 'lst'.
    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(lst=[123, 234, 345, 456])
Namespace(lst=[456])  # Attention!

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

另一种方法是使用追加操作:

a = argparse.ArgumentParser()
a.add_argument(
    '-l', '--list',  # either of this switches
    type=int,        # /parameters/ are ints
    dest='lst',      # store in 'lst'.
    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(lst=[123, 234, 345, 456])

或者您可以编写一个自定义处理程序/操作来解析逗号分隔的值,这样您就可以这样做

-l 123,234,345 -l 456