使用argparse对未知数量的参数进行分组

问题描述:

我正在为需要能够接受一个或多个选项组的命令行程序设计用户界面。各组是一样的,但需要连在一起,就像这样:使用argparse对未知数量的参数进行分组

./myprogram.py --group1 name1,name2,pathA,pathB --group2 name3,name4,pathC,pathD 

这看起来非常笨重的用户来处理。我曾考虑过使用INI样式的configparser设置,但它也很笨拙,因为除此之外我还有很多其他参数通常都有默认值,然后我失去了处理需求的所有模块的功能,检查如果文件存在等。

有没有人有任何想法,我怎么能最好的结构我的ArgumentParser,以便我可以让用户一起提供给定组的四个所需的输入?我没有和逗号分隔列表结婚,这只是一个例子。它实际上会好得多,如果他们能够进入某种键值对,如

./myprogram.py --group1 firstname:name1 secondname:name2 firstpath:pathA secondpath:pathB 

但我知道,argparse不支持dict类型,任何黑客,使这将是用户甚至更少-友善。

可以使用nargs=4'append'动作:

import argparse 

parser = argparse.ArgumentParser() 
parser.add_argument('--group', nargs=4, action='append') 

print parser.parse_args() 

它会被称为:

$ python ~/sandbox/test.py --group 1 2 3 4 --group 1 2 3 4 
Namespace(group=[['1', '2', '3', '4'], ['1', '2', '3', '4']]) 

从这里,你可以解析键值对,如果你想。


另一种选择是使用自定义动作做解析 - 这里有一个简单的一个,其接受--group key:value key2:value2 ... --group ...

import argparse 

class DictAction(argparse.Action): 
    def __init__(self, *args, **kwargs): 
     super(DictAction, self).__init__(*args, **kwargs) 
     self.nargs = '*' 

    def __call__(self, parser, namespace, values, option_string=None): 
     # The default value is often set to `None` rather than an empty list. 
     current_arg_vals = getattr(namespace, self.dest, []) or [] 
     setattr(namespace, self.dest, current_arg_vals) 
     arg_vals = getattr(namespace, self.dest) 
     arg_vals.append(dict(v.split(':') for v in values)) 

parser = argparse.ArgumentParser() 
parser.add_argument('--group', action=DictAction) 

print parser.parse_args() 

这有没有检查形式的参数(这样用户可以胡来TypeError如果key:value未正确格式化),并且如果您想将其限制为指定的键,则需要将其构建为...但这些细节应该足够容易添加。您也可以要求他们使用self.nargs = 4DictAction.__init__中提供4个值。

+0

我喜欢这个,我没有意识到action = append可以像那样工作。我仍然认为键值部分会有点难看,但命令行输入很难开始。 –

+0

@IanFiddes - 我已经添加了一个key:value解析示例。 – mgilson