位置参数之前的argparse可选参数

时间:2012-11-12 15:29:58

标签: python argparse

我想知道是否有可能使用可选参数的参数跟随位置参数。理想情况下,输入命令行的最后一个参数将始终应用于'testname'。

import argparse
parser = argparse.ArgumentParser(description='TAF')
parser.add_argument('-r','--release',nargs='?',dest='release',default='trunk')
parser.add_argument('testname',nargs='+')
args = parser.parse_args()

我希望这两个调用都能将smoketest应用于testname,但第二个调用会导致错误。

>> python TAF.py -r 1.0 smoketest
>> python TAF.py -r smoketest
TAF.py: error: too few arguments

我意识到将位置参数移动到前面会导致可选参数的正确行为,但这不是我正在寻找的格式。选择标志看起来像一个有吸引力的替代方案,但它会抛出错误而不是忽略不匹配的项目。

编辑: 我找到了一个围绕这个的hacky方式。如果有人有更好的解决方案我会很感激。

import argparse
parser = argparse.ArgumentParser(description='TAF')
parser.add_argument('-r','--release',nargs='?',dest='release',default='trunk')
parser.add_argument('testname',nargs=argparse.REMAINDER)
args = parser.parse_args()

if not args.testname:
    args.testname = args.release
    args.release = ''

1 个答案:

答案 0 :(得分:4)

documentation中所述:

  

'?'。如果可能,将从命令行使用一个参数,   并作为单个项目生产。如果不存在命令行参数,   将生成默认值。请注意,对于可选   参数,还有一个例子 - 选项字符串存在   但后面没有命令行参数。在这种情况下的价值   来自const将会产生。

因此,使用'?'无法获得所需的行为。可能你可以使用argparse.Action编写一些hack并干预之前的结果。(1)

我认为更好的解决方案是拆分该选项的功能。使它成为一个需要参数的选项(但选项本身是可选的)并添加一个不带参数的选项,将版本设置为'trunk'。通过这种方式,您可以获得相同的结果,而无需任何黑客攻击。我认为界面更简单。

在你的例子中:

python TAF.py -r smoketest

很明显,smoketest将被解释为-r的参数。至少遵循unix约定。如果您想保留nargs='?',则用户必须使用--

$ python TAF.py -r -- sometest
Namespace(release=None, testname=['sometest'])   #parsed result

(1)关于如何执行此操作的想法:检查选项是否有参数。如果有一个检查它是否是有效的测试名称。如果是这样,请手动插入testname并将release设置为默认值。你还必须设置一个“标志”,告诉你这件事发生了。

现在,在解析sys.argv之前,您必须重定向sys.stderr。在进行解析时,您必须捕获SystemExit,检查stderr并查看错误是否“参数太少”,检查是否设置了标志,如果是,请忽略错误并继续运行,否则您应重新打印到原始stderr错误消息并退出。

这种方法看起来并不健壮,而且可能是错误的。