我正在使用argparse构建一个包含子命令的命令:
分支命令[全局FLAGS]子命令[FLAGS]
我希望全局标志在子命令之前或之后都能工作。有没有一种干净的方法可以做到这一点,而不需要重复代码?
例如:
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='subparser_name')
parser.add_argument('--disable') # This flag...
sp = subparsers.add_parser('compile')
sp.add_argument('zones', nargs='*')
sp.add_argument('--disable') # Is repeated...
sp = subparsers.add_parser('launch')
sp.add_argument('zones', nargs='*')
sp.add_argument('--disable') # over and over...
我想为许多旗帜做这件事,所以一遍又一遍地重复自己似乎。。。不连贯的。
这是parents
argparse功能的完美用例:
有时,几个解析器共享一组共同的参数。相当地而不是重复这些参数的定义,单个解析器带有所有共享的参数并传递给parents=argument可以使用ArgumentParser。
定义基本父ArgumentParser
,添加将在子分析器之间共享的参数。然后,添加子解析器,并通过提供parents
关键字参数将基本解析器设置为父解析器:
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='subparser_name')
base_subparser = argparse.ArgumentParser(add_help=False)
# define common shared arguments
base_subparser.add_argument('--disable')
sp = subparsers.add_parser('compile', parents=[base_subparser])
# define custom arguments
sp = subparsers.add_parser('launch', parents=[base_subparser])
# define custom arguments
注意,这里的add_help=False
有助于避免help
参数冲突的问题。
另请参阅:Python argparse-向多个子分析器添加参数。
我在您的示例中看到两个问题:
1) 在解析器和子解析器中都使用了"--disable"。嵌套参数分析器处理重叠的CCD_ 6。
2) 子分析器中重复的一组参数。parents
无疑是一种简化方法。但你可以很容易地编写自己的代码:
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='subparser_name')
parser.add_argument('--disable', dest='main_disable') # This flag...
for name in ['compile', 'launch']:
sp = subparsers.add_parser(name)
sp.add_argument('zones', nargs='*')
sp.add_argument('--disable', dest=name+'_disable') # Is repeated...
您要求的是argparse解决方案,但由于您也要求Pythonic解决方案,我将故意使用包docopt
:提出一种替代方案
获取:
$ pip install docopt
将代码写入mycommand
文件:
"""
Usage:
mycommand compile [--disable] <zone>...
mycommand launch [--disable] <zone>...
Arguments:
<zone> zone name
Options:
-h --help
--disable disable
"""
from docopt import docopt
if __name__ == "__main__":
args = docopt(__doc__)
print args
然后从命令行调用:
基本帮助(无参数):
$ python mycommand
Usage:
mycommand compile [--disable] <zone>...
mycommand launch [--disable] <zone>...
寻求帮助:
$ python mycommand -h
Usage:
mycommand compile [--disable] <zone>...
mycommand launch [--disable] <zone>...
Arguments:
<zone> zone name
Options:
-h --help
--disable disable
使用compile子命令:
$ python mycommand compile zoneAlfa zoneBeta
{'--disable': False,
'<zone>': ['zoneAlfa', 'zoneBeta'],
'compile': True,
'launch': False}
添加标志--禁用:
$ python mycommand compile --disable zoneAlfa zoneBeta
{'--disable': True,
'<zone>': ['zoneAlfa', 'zoneBeta'],
'compile': True,
'launch': False}
启动子命令也起作用:
$ python mycommand launch --disable zoneAlfa zoneBeta
{'--disable': True,
'<zone>': ['zoneAlfa', 'zoneBeta'],
'compile': False,
'launch': True}
我对参数解析器的使用也是从argparse开始的,我讨厌代码的复杂性,这是做某事所必需的。
后来我转向了plac
,这是一种非常有效的方法,可以将python函数转换为控制台上非常有用的命令。
尽管如此,我还是受到了一套规则的限制,这些规则在很多情况下对我来说都不是很清楚。使用docopt
,我很感激,我可以按照POSIX的标准规则首先编写docstring,然后在代码中使用它。如果你关心论点的验证,我会指导你这个伟大的包的样本。