将可选列表传递给 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+A
的re
匹配器。
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的主要内容,如果未能解决你的问题,请参考以下文章
如何将可选 ID 从 Route 传递给 Laravel 控制器?
python如何将可选参数或关键字参数从一个函数传递到另一个函数?