argparse位置参数前的可选参数

13

我想知道是否可以在具有可选参数的参数后面跟随一个位置参数。理想情况下,输入到命令行中的最后一个参数将始终应用于'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()

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

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

我意识到将位置参数移至开头会导致可选参数的正确行为,但这不完全是我要寻找的格式。choices标志看起来是一个有吸引力的替代方案,然而它会抛出错误而不是忽略不匹配的项。

编辑: 我已经找到了一个临时解决办法。如果有更好的解决方案,我将不胜感激。

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个回答

6
正如文档中所述:nargs
'?'。如果可能,将从命令行中使用一个参数,并作为单个项生成。如果没有命令行参数,则将产生默认值。请注意,对于可选参数,还有另一种情况 - 选项字符串存在但不跟随命令行参数。在这种情况下,将生成来自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。在进行解析时,必须捕获 SystemExit,检查 stderr 并查看错误是否是“参数太少”,检查标志是否已设置,若是,则忽略错误并继续运行;否则,应将错误消息重新打印到原始的 stderr 并退出。

此方法看起来不太健壮,可能存在错误。


谢谢您的回复。我同意可以通过为testname参数添加前缀或者像我提到的那样在其他参数之前列出它们来实现清晰明了的操作。 - Landon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接