Python argparse:在帮助字符串中获取subparser程序的名称

时间:2016-12-28 21:03:48

标签: python argparse subparsers

我正在为包含各种子分析器的python模块编写一个参数解析器。我的目标是让一个参数共享,其Argument构造函数被传递给多个子节点:

from argparse import ArgumentParser
parser = ArgumentParser(prog = 'master')
parser1 = ArgumentParser(help = None)
parser1.add_argument('foo', type = int, help = 'Number of times to process %(prog)s') # Line of interest
parser2 = ArgumentParser(help = None)
parser2.add_argument('--bar', type = int, default = 0, help = 'Start at this number')
parser3 = ArgumentParser(help = None)
parser3.add_argument('--baz', type = str, default = 'DEFAULT', help = 'Init file with this text')
subparsers = parser.add_subparsers()
sp1 = subparsers.add_parser('prog1', parents = [parser1, parser2])
sp2 = subparsers.add_parser('prog2', parents = [parser1, parser3])
parser.parse_args('prog1 -h'.split())

所需的输出类似于

usage: master prog1 [-h] [--bar BAR] foo

positional arguments:
  foo            Number of times to process prog1

optional arguments:
  -h, --help     show this message and exit
  --bar          Start at this number

当我使用这个确切的设置时,我会在master prog1的帮助字符串中获得prog1而不是foo。我应该在标记为#Line of interest的行中更改哪些内容以获得所需的结果?

2 个答案:

答案 0 :(得分:0)

这不是您问题的直接答案,但我会使用Click_来解决您的问题。

Click_有三点:

  1. 任意命令嵌套
  2. 自动帮助页面生成
  3. 支持在运行时延迟加载子命令

答案 1 :(得分:0)

我可以解释发生了什么,但可能无法提供解决方案。

简短的回答是sp1.progusage格式和帮助热线中的%(prog)s值使用。它构建时考虑到usage行。

===============

sp1 = subparsers.add_parser('prog1', parents = [parser1, parser2])

创建一个解析器,并添加parents的参数。 add_parserclass _SubParsersAction(subparser Action类)的方法。并且使用以下命令创建该解析器的prog属性:

     if kwargs.get('prog') is None:
        kwargs['prog'] = '%s %s' % (self._prog_prefix, name)

您应该能够使用print(sp1.prog)看到此属性(我希望'master prog1')。这是usage行以及%(prog)s的任何帮助行中使用的值。

subparsers._prog_prefix源自parser.prog(有关详细信息,请参阅add_subparsers代码)。但您也可以指定prog参数:

sp1 = subparsers.add_parser('prog1', parents = [parser1, parser2], prog='prog1')

这应该纠正help行中的字符串。但它也会改变字符串usage

您还可以为子分析器提供明确的usage

sp1 = subparsers.add_parser('prog1', parents = [parser1, parser2], prog='prog1', usage='master prog1 ...')

如果不对HelpFormatter进行手术,我认为您不能在帮助热线中更改prog,也不会在使用中更改它。

考虑到parents的工作方式,您无法更改prog1 foo的帮助热线,也无法更改prog2 foo的帮助热线。 parents通过引用复制Action对象,因此两个子分析器共享foo Action对象。

你们不得不放弃parents方法,至少对于这个论点,并对名称进行硬编码。如果您需要将参数添加到多个子分析器,请编写一个小实用程序函数以方便它。 parents机制只是(通常)方便,可以节省一些打字/编辑。

===================

这个经过修改的脚本将说明我的观点

parser = ArgumentParser(prog = 'master')

parser1 = ArgumentParser(add_help = False)
fooarg=parser1.add_argument('foo', type = int, help = 'foo prog: %(prog)s') # Line of interest
parser2 = ArgumentParser(add_help = False)
parser2.add_argument('--bar', type = int, default = 0, help = 'Start at this number')
parser3 = ArgumentParser(add_help = False)
parser3.add_argument('--baz', type = str, default = 'DEFAULT', help = 'Init file with this text')

subparsers = parser.add_subparsers(prog='subparsers')
sp1 = subparsers.add_parser('prog1', parents = [parser1, parser2], prog='name1')
sp2 = subparsers.add_parser('prog2', parents = [parser1, parser3])

#parser.print_help()

# fooarg is an Action for both subparsers
# print(fooarg.help)
# fooarg.help = 'FOO HELP'

print('==>sp1 prog:', sp1.prog)
sp1.print_help()
print('==>sp2 prog:', sp2.prog)
sp2.print_help()

sp1.prog = 'custom'
sp1.print_help()

# addition
fooarg.default = 'default'
fooarg.metavar = 'META'
fooarg.help = 'prog: %(prog)s, dest=%(dest)s, nargs=%(nargs)s, type=%(type)s, default=%(default)s'
sp1.print_help()

最后一位向帮助添加了一堆Action属性。但是prog是唯一来自parser

的人
positional arguments:
  META        prog: custom, dest=foo, nargs=None, type=int, default=default