控制argparse帮助参数列表的格式?

43
import argparse
parser = argparse.ArgumentParser(prog='tool')
args = [('-u', '--upf', 'ref. upf', dict(required='True')),
        ('-s', '--skew', 'ref. skew', {}),
        ('-m', '--model', 'ref. model', {})]
for args1, args2, desc, options in args:  
     parser.add_argument(args1, args2, help=desc, **options)

parser.print_help()

输出:

usage: capcheck [-h] -u UPF [-s SKEW] [-m MODEL]

optional arguments:
  -h, --help            show this help message and exit
  -u UPF, --upf UPF     ref. upf
  -s SKEW, --skew SKEW  ref. skew
  -m MODEL, --model MODEL
                        ref. model

如何在运行脚本时,以与 -h 选项不同的方式将参考模型(ref. model)-m MODEL, --model MODEL打印在同一行上?

5个回答

49
你可以提供 formatter_class 参数:
parser = argparse.ArgumentParser(prog='tool',
  formatter_class=lambda prog: argparse.HelpFormatter(prog,max_help_position=27))

args = [('-u', '--upf', 'ref. upf', dict(required='True')),
        ('-s', '--skew', 'ref. skew', {}),
        ('-m', '--model', 'ref. model', {})]
for args1, args2, desc, options in args:  
     parser.add_argument(args1, args2, help=desc, **options)

parser.print_help()

注意:实现argparse.HelpFormatter的是私有的,只有名称是公共的。因此,代码可能在将来版本的argparse中停止工作。请在http://bugs.python.org/上提出功能请求,以提供公共接口来自定义max_help_position

usage: tool [-h] -u UPF [-s SKEW] [-m MODEL]

optional arguments:
  -h, --help               show this help message and exit
  -u UPF, --upf UPF        ref. upf
  -s SKEW, --skew SKEW     ref. skew
  -m MODEL, --model MODEL  ref. model

8
受 @jfs 回答的启发,我想出了以下解决方案:
def make_wide(formatter, w=120, h=36):
    """Return a wider HelpFormatter, if possible."""
    try:
        # https://dev59.com/Dm035IYBdhLWcg3wW-31#5464440
        # beware: "Only the name of this class is considered a public API."
        kwargs = {'width': w, 'max_help_position': h}
        formatter(None, **kwargs)
        return lambda prog: formatter(prog, **kwargs)
    except TypeError:
        warnings.warn("argparse help formatter failed, falling back.")
        return formatter

有了这个功能,您可以使用任何您喜欢的HelpFormatter进行调用:

parser = argparse.ArgumentParser(
    formatter_class=make_wide(argparse.ArgumentDefaultsHelpFormatter)
)

或者

parser = argparse.ArgumentParser(
    formatter_class=make_wide(argparse.HelpFormatter, w=140, h=20)
)

这段代码的作用是确保使用widthmax_help_position参数可以创建更宽的格式化器。如果私有API发生更改,make_wide会通过TypeError进行记录,然后返回未更改的格式化器。这将使部署应用程序的代码更加可靠。
如果您有任何建议可以使此代码更具Python风格,我非常欢迎。

使用argparse.RawTextHelpFormatter与https://stackoverflow.com/a/3853776/2142003中提到的方法一起使用,以实现完全的格式控制。 - undefined

2
如果您正在为您的ArgumentParser提供自定义的formatter_class,请注意:
parser = argparse.ArgumentParser(formatter_class=help_formatter)

然后使用子解析器,格式化程序只适用于顶级帮助信息。为了在所有子解析器中使用相同(或其他)格式化程序,您需要为每个add_parser调用提供formatter_class参数:

subparsers = parser.add_subparsers(metavar="ACTION", dest="action")
child_parser = subparsers.add_parser(
    action_name, formatter_class=help_formatter
)

1

由于argparse库尝试使用环境变量获取终端宽度,因此我们也可以设置这个变量,让argparse完成其工作。

import os
import argparse

rows, columns = os.popen('stty size', 'r').read().split()
os.environ["COLUMNS"] = str(columns)

parser = argparse.ArgumentParser(etc...

已在RHEL/Python 2.7.5上进行了测试和批准

感谢https://dev59.com/G3RB5IYBdhLWcg3wn4jc#943921获取真实终端宽度的贡献


0
另一种方法:劫持sys.argv,检查其中是否包含--help和-h参数,如果找到了,则使用argparse.format_help提取帮助文本,进行处理并打印输出,最后退出。
import  sys, re, argparse 

RGX_MID_WS = re.compile(r'(\S)\s{2,}')

def main(argv):

#   note add_help = False
    parser = argparse.ArgumentParser(description = '%(prog)s: testing help mods', formatter_class= argparse.RawTextHelpFormatter, add_help = False)

    parser.add_argument('bar', nargs='+', help='two bars that need to be frobbled')
    parser.add_argument('--foo', action='store_true', help='foo the bars before frobbling\nfoo the bars before frobbling')
    parser.add_argument('--xxxxx', nargs=2, help='many xes')
    parser.add_argument('--bacon', help ='a striped food')
    parser.add_argument('--badger', help='in a striped pyjamas')
    parser.add_argument('--animal', dest='animal', choices=('zabra', 'donkey', 'bat') ,help ='could be one of these')

#   may exit
    lArgs = help_manage(parser)
    args = parser.parse_args() # args = lArgs

    print('bars are: ', args.bar)


def help_manage(parser):
    """
    check for -h, --help, -h in a single-letter cluster;
    if none found, return, otherwise clean up help text and exit
    """

    lArgs = sys.argv[1:]
    lArgsNoHelp = [sOpt for sOpt in lArgs if (not sOpt in ('--help', '-h')) and not (sOpt[0] == '-' and sOpt[1] != '-' and 'h' in sOpt)]

#   no change?  then no --help params
    if len(lArgsNoHelp) == len(lArgs): return

    sHelp = parser.format_help()

#   to see help as formated by argparse, uncomment: 
#   print(sHelp)
#   exit() 

    for sLine in sHelp.split('\n'): print(clean_line(sLine))

    exit() 

def clean_line(sLine):
    """
    this is just an example, and goes nowhere near covering all possible
    argument properties
    """
#   avoid messing with usage: lines
    if 'usage' in sLine: return sLine
    if sLine.startswith('  ') and '[' in sLine: return sLine

    if sLine.endswith(' arguments:'): return sLine + '\n'

    sLine = sLine.lstrip()

    sLine = RGX_MID_WS.sub(r'\1\n', sLine)
    if sLine.startswith('-'): sLine = '\n' + sLine
    return sLine.replace('{', '\n(can be: ').replace('}', ')').replace('\n\n', '\n')

if __name__ == '__main__':

    bRes =  main(sys.argv[1:])
    sys.exit(bRes)

无格式的帮助:

usage: argparse_fix_min2.py [--foo] [--xxxxx XXXXX XXXXX] [--bacon BACON]
                                [--badger BADGER] [--animal {zabra,donkey,bat}]
                                bar [bar ...]

    argparse_fix_min2.py: testing help mods

    positional arguments:
      bar                   two bars that need to be frobbled

    optional arguments:
      --foo                 foo the bars before frobbling
                            foo the bars before frobbling
      --xxxxx XXXXX XXXXX   many xes
      --bacon BACON         a striped food
      --badger BADGER       in a striped pyjamas
      --animal {zabra,donkey,bat}
                            could be one of these

带格式:

usage: argparse_fix_min2.py [--foo] [--xxxxx XXXXX XXXXX] [--bacon BACON]
                                [--badger BADGER] [--animal {zabra,donkey,bat}]
                                bar [bar ...]

    argparse_fix_min2.py: testing help mods

    positional arguments:

    bar
    two bars that need to be frobbled

    optional arguments:


    --foo
    foo the bars before frobbling
    foo the bars before frobbling

    --xxxxx XXXXX XXXXX
    many xes

    --bacon BACON
    a striped food

    --badger BADGER
    in a striped pyjamas

    --animal 
    (can be: zabra,donkey,bat)
    could be one of these

    """


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