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

当前回答

在add_argument()中,type只是一个可调用的对象,它接收字符串并返回选项值。

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]"

其他回答

将chepner的评论应用到Lunguini的回答中:

import argparse, json                                                                                            
parser = argparse.ArgumentParser()                                                                               
parser.add_argument('-l', '--list', type=lambda a: json.loads(a), default="[]",                                  
                    help="String formatted as list wrapped in []")                                               
args = parser.parse_args()                                                                                       
print(args.list)                                                                                                 

用法:

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

在add_argument()中,type只是一个可调用的对象,它接收字符串并返回选项值。

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]"

请注意,如果你传递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年,所以不太可能得到解决。

如果你有一个嵌套列表,其中内部列表有不同的类型和长度,你想要保留类型,例如:

[[1,2], ["foo", "bar"], [3.14, "baz", 20]]]

然后你可以使用@sam-mason提出的解决方案来解决这个问题,如下所示:

from argparse import ArgumentParser
import json

parser = ArgumentParser()
parser.add_argument('-l', type=json.loads)
parser.parse_args(['-l', '[[1,2],["foo","bar"],[3.14,"baz",20]]'])

这使:

Namespace(l=[[1, 2], ['foo', 'bar'], [3.14, 'baz', 20]])

我认为最优雅的解决方案是传递一个lambda函数给“类型”,正如Chepner所提到的。除此之外,如果你事先不知道列表的分隔符是什么,你也可以传递多个分隔符给re.split:

# python3 test.py -l "abc xyz, 123"

import re
import argparse

parser = argparse.ArgumentParser(description='Process a list.')
parser.add_argument('-l', '--list',
                    type=lambda s: re.split(' |, ', s),
                    required=True,
                    help='comma or space delimited list of characters')

args = parser.parse_args()
print(args.list)


# Output: ['abc', 'xyz', '123']