将可选列表传递给 argparse

Pass an optional list to argparse

是否有比 pass a delimited string and parse it later 更优雅的方式将可选的整数列表传递给 argparse?我也有一个位置参数。

parser.add_argument('--ids', type=int, nargs='+')
parser.add_argument('cmd')

不起作用,因为 argparse 试图获取 cmd 并抱怨它不是整数。

理想情况下,我想用

之一执行
program.py --ids 6,32,12 refresh
program.py --ids 6 32 12 refresh

或者类似的东西,也能

program.py refresh

-- 是 'positional arguments start here'.

的一种方便表达方式

使用您的解析器,这些工作:

program.py refresh   # sets ids=None
program.py refresh --ids 1 2 3
program.py --ids 1 2 3 -- refresh

如果您不喜欢 None.

,您可以给 --ids 参数一个默认值(例如 [])

program.py refesh --ids 1,2,3 的任何问题都是由于 shell 如何拆分您的命令行。查看 sys.argv 列表。

出现 program.py --ids 1 2 3 refresh 的问题是因为在处理 --ids 时,解析器会尝试使用其后所有明显不是标志的字符串(例如带有“-”)。它不使用 'int' 类型来测试哪些使用哪些离开。

现在如果 ids 是位置的,它将处理 1 2 3 refresh:

parser.add_argument('ids',type=int,nargs='+')
parser.add_argument('cmd')
parser.parse_args('1 2 3 refresh'.split())

但那是因为解析器使用不同的策略将字符串分配给多个位置参数。它使用一个 re 匹配器,看起来像 A+A.


Kevin 的 type 方法可以用一个简单的函数更好地实现:

def mytype(astring):
    ll = astring.split(',')
    return [int(l) for l in ll]
parser.add_argument('--ids', type=mytype)

它可以被推广来处理像“1 2 3”这样的带引号的字符串。 type 可以是接受字符串和 returns 所需值的任何函数,如果无法进行转换则会引发错误。

如果你只想解析形式为 --ids 1,2,3 的参数(没有空格),你可以使用这样的东西:

def convert(argument):
    return map(int, argument.split(','))  # 3.x: consider wrapping in list()

parser.add_argument('--ids', type=convert)

这不会处理由空格分隔的参数,尽管您可以使用更智能的 convert() 函数来减轻这种情况。但是,您随后需要引用它们,否则 shell 会将它们作为单独的参数传递。