1

我正在为带有各种子解析器的 python 模块编写参数解析器。我的目标是有一个共享的参数,其参数构造函数被传递给多个孩子:

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不是. 我应该在标记的行中更改什么以获得所需的结果?prog1foo#Line of interest

4

2 回答 2

0

这不是您问题的直接答案,但我会使用Click_来完成您尝试做的事情。

点击_分三点:

  1. 命令的任意嵌套
  2. 自动帮助页面生成
  3. 支持在运行时延迟加载子命令
于 2016-12-28T21:25:18.600 回答
0

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

简短的回答是,sp1.prog它的usage格式和%(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

你也可以给 subparser 一个明确的usage

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

如果不做手术,HelpFormatter我认为你不能改变prog帮助线而不改变它的用法。

并且考虑到parents工作方式,您无法更改帮助行prog1 foo而不更改prog2 foo. parents通过引用复制 Action 对象,因此两个子解析器共享fooAction 对象。

你们许多人必须放弃这种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()

最后一点将一堆动作属性添加到帮助中。但是prog是唯一一个来自parser

positional arguments:
  META        prog: custom, dest=foo, nargs=None, type=int, default=default
于 2016-12-28T22:02:29.970 回答