我想知道是否有可能在一个带有可选参数的参数后面有一个位置参数.理想情况下,输入命令行的最后一个参数将始终应用于'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()
Run Code Online (Sandbox Code Playgroud)
我希望这两个调用都能将smoketest应用于testname,但第二个调用会导致错误.
>> python TAF.py -r 1.0 smoketest
>> python TAF.py -r smoketest
TAF.py: error: too few arguments
Run Code Online (Sandbox Code Playgroud)
我意识到将位置参数移动到前面将导致可选参数的正确行为,但这不是我正在寻找的格式.选择标志看起来像一个有吸引力的替代方案,但它会抛出错误而不是忽略不匹配的项目.
编辑:我发现了一个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 = ''
Run Code Online (Sandbox Code Playgroud)
如文档中所述:
'?'。如果可能的话,将从命令行使用一个参数,并将其作为单个项目生成。如果不存在命令行参数,则将生成默认值。请注意,对于可选参数,还有另一种情况 - 选项字符串存在,但后面没有命令行参数。在这种情况下,将生成 const 的值。
因此,使用 无法获得您想要的行为'?'。也许您可以使用argparse.Action和干预之前的结果编写一些 hack。(1)
我认为更好的解决方案是拆分该选项的功能。使其成为需要参数的选项(但选项本身是可选的),并添加一个不带参数的选项,将发布设置为'trunk'。通过这种方式,您无需进行任何修改即可获得相同的结果。我也认为界面更简单。
在你的例子中:
python TAF.py -r smoketest
Run Code Online (Sandbox Code Playgroud)
很明显,这smoketest将被解释为 的参数-r。至少遵循 UNIX 约定。如果您想保留,nargs='?'则用户必须使用--:
$ python TAF.py -r -- sometest
Namespace(release=None, testname=['sometest']) #parsed result
Run Code Online (Sandbox Code Playgroud)
(1) 关于如何执行此操作的想法:检查选项是否有参数。如果有,请检查它是否是有效的测试名称。如果有则手动放入testname并设置release为默认值。您还必须设置一个“标志”来告诉您这件事发生了。
现在,在解析之前,sys.argv您必须重定向sys.stderr。在进行解析时,您必须 catch SystemExit,检查stderr并查看错误是否是“参数太少”,检查是否设置了标志,如果是,则忽略错误并继续运行,否则您应该重新打印到原始stderr错误消息并退出。
这种方法看起来并不稳健,而且可能存在缺陷。