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

发布于 2024-10-27 13:38:28 字数 778 浏览 1 评论 0原文

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

如何打印 ref. model-m MODEL, --model MODEL 位于同一行,而不是当我使用 -h 选项运行脚本时出现在单独的行上?

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

Output:

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

How do I print ref. model in the same line as -m MODEL, --model MODEL instead of that appearing on a separate line when I run the script with -h option?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

回忆躺在深渊里 2024-11-03 13:38:29

由于 argparse 库尝试使用 COLUMNS 环境变量来获取终端宽度,因此我们也可以设置此变量,并让 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://stackoverflow.com/a/943921 以获得真正的终端宽度

As the argparse library tries to use the COLUMNS environment variable to get the terminal width, we also can set this variable, and let argparse do its job.

import os
import argparse

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

parser = argparse.ArgumentParser(etc...

Tested and approved on RHEL/Python 2.7.5

Credits to https://stackoverflow.com/a/943921 for getting the real terminal width

流云如水 2024-11-03 13:38:29

另一种方法:劫持 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

    """

Another approach: hijack sys.argv, check it for --help and -h, if found extract help text using argparse.format_help, massage it, print it, and exit.

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)

Help without formatting:

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

with formatting:

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

    """

故事和酒 2024-11-03 13:38:28

您可以提供 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 上的 max_help_position 自定义提供公共接口。 python.org/

输出

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

You could supply formatter_class argument:

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

Note: Implementation of argparse.HelpFormatter is private only the name is public. Therefore the code might stop working in future versions of argparse. File a feature request to provide a public interface for the customization of max_help_position on http://bugs.python.org/

Output

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
秋心╮凉 2024-11-03 13:38:28

受到@jfs答案的启发,我提出了这个解决方案:

def make_wide(formatter, w=120, h=36):
    """Return a wider HelpFormatter, if possible."""
    try:
        # https://stackoverflow.com/a/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 进行记录,并且格式化程序将原样返回。这应该会使代码对于已部署的应用程序更加可靠。

我欢迎任何让这变得更加Pythonic的建议。

Inspired by @jfs's answer, I have come up with this solution:

def make_wide(formatter, w=120, h=36):
    """Return a wider HelpFormatter, if possible."""
    try:
        # https://stackoverflow.com/a/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

Having that, you can call it with any HelpFormatter that you like:

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

or

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

What this does is make sure that the wider formatter can actually be created using the width and max_help_position arguments. If the private API changes, that is noted by make_wide by a TypeError and the formatter is returned unchanged. That should make the code more reliable for deployed applications.

I'd welcome any suggestions to make this more pythonic.

驱逐舰岛风号 2024-11-03 13:38:28

如果您向 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
)

If you are providing a custom formatter_class to your ArgumentParser

parser = argparse.ArgumentParser(formatter_class=help_formatter)

and then use subparsers, the formatter will only apply to the top-level help message. In order to use the same (or some other) formatter for all subparsers, you need to provide formatter_class argument for each add_parser call:

subparsers = parser.add_subparsers(metavar="ACTION", dest="action")
child_parser = subparsers.add_parser(
    action_name, formatter_class=help_formatter
)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文