Don't show long options twice in print_help() from argparse

与世无争的帅哥 提交于 2019-11-29 12:18:10

问题


I have the following code:

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()

Which gives me output like this:

%./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

I would very much like to know how I can 'group' commands that have two versions (ie. long options) which each also show a metavar.

This is mostly an aesthetic issue on my side, but I would still like to fix this. I have been reading manuals and texts on the internet, but either the information just isn't there or I am totally missing something here :)


回答1:


Another solution, using custom descriptions

if you set the metavar='', the help line becomes:

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

Here I suppress the regular help lines, and replace them with the description lines for a group:

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>

Or you could put that information in the regular description. You already are using a custom usage line.




回答2:


Putting hpaulj's answer into actual code, something like this works:

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)

To additionally extend the default column size for help variables, add constructor to CustomHelpFormatter:

def __init__(self, prog):
    super().__init__(prog, max_help_position=40, width=80)

Seeing it in action:

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



回答3:


Is the problem that <domain> is repeated in the help line?:

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

The argparse HelpFormatter does not give the user much control over this part of the display. As you have shown, you can set the usage line, the help text, and the metavar.

You would have to subclass the HelpFormatter, and change one of the functions to produce something like:

-d, --domain <domain>

It doesn't look like a complicated change, probably to the HelpFormatter._format_action_invocation method. But you need to be more explicit about what you want.



来源:https://stackoverflow.com/questions/18275023/dont-show-long-options-twice-in-print-help-from-argparse

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!