我们假设我有一个脚本select_libs.py
,它允许您选择在某些构建过程中包含哪些库。运行此脚本时,我希望能够指定库名称,分支和版本。以下是一些用例。
select_libs.py
select_libs.py opencv stable 3.4.1
select_libs.py opencv stable 3.4.1 boost development 1.67.0
所以我想象一下这么简单:
import argparse
branches = ["legacy", "stable", "development"]
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(help='lib configuration')
opencv_parser = subparsers.add_parser("opencv")
opencv_parser.add_argument("opencv_build", choices=branches)
opencv_parser.add_argument("opencv_version", type=str)
boost_parser = subparsers.add_parser("boost")
boost_parser.add_argument("boost_build", choices=branches)
boost_parser.add_argument("boost_version",type=str)
cmd_options = parser.parse_args()
前两个用例都有效,但第三个:
select_libs.py opencv stable 3.4.1 boost development 1.67.0
产生此错误:
error: unrecognized arguments: boost development 1.67.0
在我的脑海中,这应该有效,因为每个解析器都有两个位置参数,因此它应该知道boost
不是opencv
的参数并相应地触发boost
解析器。显然我错了,但我错过了什么,如何让它按预期工作(如果可能的话)?
我目前的Python版本是3.5.2
。
答案 0 :(得分:1)
Argparse不适合这种事情。 add_subparsers
假设将使用正好一个子命令,因此如果您尝试同时设置opencv
和boost
,则会引发错误。除此之外,argparse没有与其他参数相关联的参数概念。
如果您不介意使用关键字选项而非位置选项,则可以使用this answer中的解决方案:
argv = '-l opencv -b stable -v 3.4.1 -l boost -b development -v 1.67.0'.split()
parser = argparse.ArgumentParser()
parent = parser.add_argument('-l', '--lib', choices=['opencv', 'boost'], action=ParentAction)
parser.add_argument('-b', '--build', action=ChildAction, parent=parent)
parser.add_argument('-v', '--version', action=ChildAction, parent=parent)
args = parser.parse_args(argv)
print(args)
# output:
# Namespace(lib=OrderedDict([('opencv', Namespace(build='stable',
# version='3.4.1')),
# ('boost', Namespace(build='development',
# version='1.67.0'))]))
使用nargs
参数使其成为位置和命名参数的混合:
argv = '-l opencv stable 3.4.1 -l boost development 1.67.0'.split()
parser = argparse.ArgumentParser()
parent = parser.add_argument('-l', '--lib', nargs=3, action='append')
args = parser.parse_args(argv)
print(args)
# output:
# Namespace(lib=[['opencv', 'stable', '3.4.1'],
# ['boost', 'development', '1.67.0']])
手动解析参数:
argv = 'opencv stable 3.4.1 boost development 1.67.0'.split()
args = {}
argv_itr = iter(argv)
for lib in argv_itr:
args[lib] = {'build': next(argv_itr),
'version': next(argv_itr)}
print(args)
# output:
# {'opencv': {'build': 'stable',
# 'version': '3.4.1'},
# 'boost': {'build': 'development',
# 'version': '1.67.0'}}