允许在子命令之后使用argparse全局标志



我正在使用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,然后在代码中使用它。如果你关心论点的验证,我会指导你这个伟大的包的样本。

相关内容

  • 没有找到相关文章

最新更新