12

我想知道是否可以在带有可选参数的参数后面加上位置参数。理想情况下,输入命令行的最后一个参数将始终适用于“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

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

编辑:我找到了一种解决方法。如果有人有更好的解决方案,我将不胜感激。

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 = ''
4

1 回答 1

4

文档中所述:

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

因此,您想要的行为无法使用'?'. 可能您可以使用argparse.Action和干预以前的结果编写一些技巧。(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. 解析时必须catch SystemExit,检查stderr错误是否是“参数太少”,检查标志是否设置,如果设置则忽略错误并继续运行,否则应重新打印stderr错误消息并退出.

这种方法看起来并不健壮,而且可能有问题。

于 2012-11-12T16:23:40.013 回答