将可选列表传递给 argparse

Posted

技术标签:

【中文标题】将可选列表传递给 argparse【英文标题】:Pass an optional list to argparse 【发布时间】:2015-05-16 07:40:38 【问题描述】:

有没有比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

【问题讨论】:

您可以通过将任意可调用对象作为type 传递来立即而不是稍后解析字符串。 @Kevin 以perfect_square 为例? 是的,没错。您可以使用operator.methodcaller('split', ',') 之类的东西作为您的type,自动以逗号分隔。 @Kevin 你应该把你的 cmets 变成一个答案 【参考方案1】:

-- 是说“位置参数从这里开始”的一种方便方式。

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

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())

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


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 可以是任何接受字符串并返回所需值的函数,如果无法进行转换则会引发错误。

【讨论】:

【参考方案2】:

如果您只想解析 --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 会将它们作为单独的参数传递。

【讨论】:

以上是关于将可选列表传递给 argparse的主要内容,如果未能解决你的问题,请参考以下文章

reactjs中如何将可选元素作为prop传递给组件

如何将可选视图传递给 SwiftUI 中的另一个视图?

如何将可选 ID 从 Route 传递给 Laravel 控制器?

python如何将可选参数或关键字参数从一个函数传递到另一个函数?

Python:当列表仅在运行时确定时,如何将可迭代列表传递给 zip?

将可选参数优化传递到查询中