【问题标题】:Python argparse: Get name of subparser program in help stringPython argparse:在帮助字符串中获取子解析器程序的名称
【发布时间】:2017-05-13 04:29:41
【问题描述】:

我正在为带有各种子解析器的 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

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

【问题讨论】:

    标签: python argparse subparsers


    【解决方案1】:

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

    Click_分三点:

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

    【讨论】:

      【解决方案2】:

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

      简短的回答是sp1.prog 既以其usage 格式使用,又用作帮助行中的%(prog)s 值。它的构造考虑了usage 这一行。


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

      创建一个解析器,并添加来自parents 的参数。 add_parserclass _SubParsersAction(子解析器 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()
      

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-19
        • 2013-12-04
        • 1970-01-01
        • 1970-01-01
        • 2013-02-01
        • 2017-01-13
        • 2023-03-23
        • 2021-08-13
        相关资源
        最近更新 更多