在argparse的print_help()中不要重复显示长选项

19

我有以下代码:

parser = argparse.ArgumentParser(description='Postfix Queue Administration Tool',
        prog='pqa',
        usage='%(prog)s [-h] [-v,--version]')
parser.add_argument('-l', '--list', action='store_true',
        help='Shows full overview of all queues')
parser.add_argument('-q', '--queue', action='store', metavar='<queue>', dest='queue',
        help='Show information for <queue>')
parser.add_argument('-d', '--domain', action='store', metavar='<domain>', dest='domain',
        help='Show information about a specific <domain>')
parser.add_argument('-v', '--version', action='version', version='%(prog)s 0.1')
args = parser.parse_args()

这将给我输出如下:

%./pqa                                                                                                                        
usage: pqa [-h] [-v,--version]

Postfix Queue Administration Tool

optional arguments:
  -h, --help            show this help message and exit
  -l, --list            Shows full overview of all queues
  -q <queue>, --queue <queue>
                        Show information for <queue>
  -d <domain>, --domain <domain>
                        Show information about a specific <domain>
  -v, --version         show program's version number and exit
我非常希望知道如何将具有两个版本(即长选项)且每个版本都显示metavar的命令“分组”。这在我这边主要是个美学问题,但我仍然想解决这个问题。我一直在阅读手册和网络文本,但要么信息不全,要么我完全没有理解:)
3个回答

24
将hpaulj的答案转化为实际代码,类似于这样的代码可以工作:
class CustomHelpFormatter(argparse.HelpFormatter):
    def _format_action_invocation(self, action):
        if not action.option_strings or action.nargs == 0:
            return super()._format_action_invocation(action)
        default = self._get_default_metavar_for_optional(action)
        args_string = self._format_args(action, default)
        return ', '.join(action.option_strings) + ' ' + args_string

fmt = lambda prog: CustomHelpFormatter(prog)
parser = argparse.ArgumentParser(formatter_class=fmt)

为了进一步扩展帮助变量的默认列大小,请向CustomHelpFormatter添加构造函数:
def __init__(self, prog):
    super().__init__(prog, max_help_position=40, width=80)

看它如何运作:

usage: bk set [-h] [-p] [-s r] [-f] [-c] [-b c] [-t x y] [-bs s] [-bc c]
              [--crop x1 y1 x2 y2] [-g u r d l]
              monitor [path]

positional arguments:
  monitor                    monitor number
  path                       input image path

optional arguments:
  -h, --help                 show this help message and exit
  -p, --preview              previews the changes without applying them
  -s, --scale r              scales image by given factor
  -f, --fit                  fits the image within monitor work area
  -c, --cover                makes the image cover whole monitor work area
  -b, --background c         selects background color
  -t, --translate x y        places the image at given position
  -bs, --border-size s       selects border width
  -bc, --border-color c      selects border size
  --crop x1 y1 x2 y2         selects crop area
  -g, --gap, --gaps u r d l  keeps "border" around work area

虽然这个也能实现我的需求,但我觉得hpaulj在被采纳的答案中的代码更易读,并且完全符合我在问题中提出的要求。不过还是谢谢你额外的解释! :) - Peter van Arkel
接受的答案没有问题,但我更喜欢这个,尽管我花了一点时间才弄清楚我的默认Python版本是2.7,而且在3.4下运行时不太好用,但它非常完美。谢谢! - Madivad
另外,如果您知道如何使其在Python<3中工作,那将对我无法转换的其他脚本非常有帮助。 - Madivad

9

另一种解决方案:使用自定义描述

如果您设置metavar='',则帮助行将变为:

-q , --queue          Show information for <queue>

我在这里抑制了常规的帮助线,并用组的描述线代替它们:

parser = argparse.ArgumentParser(description='Postfix Queue Administration Tool',
        prog='pqa',
        usage='%(prog)s [-h] [-v,--version]',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        )
parser.add_argument('-l', '--list', action='store_true',
        help='Shows full overview of all queues')
g = parser.add_argument_group(title='information options',
        description='''-q, --queue <queue>     Show information for <queue>
-d, --domain <domain>   Show information about a specific <domain>''')
g.add_argument('-q', '--queue', action='store', metavar='', dest='queue',
        help=argparse.SUPPRESS)
g.add_argument('-d', '--domain', action='store', metavar='<domain>', dest='domain',
        help=argparse.SUPPRESS)
parser.add_argument('-v', '--version', action='version', version='%(prog)s 0.1')
parser.print_help()

usage: pqa [-h] [-v,--version]

Postfix Queue Administration Tool

optional arguments:
  -h, --help     show this help message and exit
  -l, --list     Shows full overview of all queues
  -v, --version  show program's version number and exit

information options:
  -q, --queue <queue>     Show information for <queue>
  -d, --domain <domain>   Show information about a specific <domain>

您可以将该信息放在常规描述中。您已经在使用自定义用法行。

我其实没有想过创建一个空的 metavar,但是你的第二个代码块更有意义,而且是一个非常简洁的解决方案! - Peter van Arkel
在翻遍了一堆代码后,这个方法对我非常有效。同时,它还可以使用colorama等工具轻松地为任何文本着色。 - liquidRock
@liquidRock,多年前的我真是个聪明的孩子 :) - hpaulj

2

问题是帮助行中重复了<domain>吗?

-d <domain>, --domain <domain>

argparse的HelpFormatter无法让用户对显示的这一部分进行太多控制。就像你展示的那样,你可以设置使用行、帮助文本和元变量。

你需要子类化HelpFormatter,并更改其中一个函数以产生类似以下内容的东西:

-d, --domain <domain>

看起来并不是一个复杂的更改,可能是针对HelpFormatter._format_action_invocation方法进行的。但你需要更明确地说明你想要什么。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接