【问题标题】:Pass an optional list to argparse将可选列表传递给 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 变成一个答案

标签: python argparse


【解决方案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 会将它们作为单独的参数传递。

    【讨论】:

      猜你喜欢
      • 2021-10-20
      • 2020-06-30
      • 2012-11-13
      • 2016-09-08
      • 2014-08-09
      • 2013-11-30
      • 2017-10-10
      • 1970-01-01
      • 2020-08-09
      相关资源
      最近更新 更多