Argparse和ArgumentDefaultsHelpFormatter。选择sys.stdin / stdout作为默认值时格式化默认值

时间:2015-12-31 10:11:21

标签: python stdout stdin argparse

我对使用argparse的ArgumentDefaultsHelpFormatter类格式化程序感兴趣(我的程序有几个子命令)。默认情况下,输入和输出参数分别设置为sys.stdin和sys.stdout。但是,这两个参数的格式可能会让用户感到困惑(例如(默认:',模式' r'在0x10028e0c0>)。有没有办法专门轻松地更改这两个参数的输出格式得到类似'默认值:STDIN'或'默认值:STDOUT'?

谢谢

import sys
import argparse

parser = argparse.ArgumentParser(prog='PROG', 
                                 formatter_class=argparse.ArgumentDefaultsHelpFormatter)

parser.add_argument('--infile',
                '-i',
                metavar='File',
                help='The input file/stream.',
                default=sys.stdin,
                type=argparse.FileType('r'),
                required=False)

parser.add_argument('--outfile',
                '-o',
                metavar='File',
                help='The output file/stream.',
                default=sys.stdout,
                type=argparse.FileType('r'),
                required=False)

parser.add_argument('--whatever-arg',
                '-w',
                type=str,
                default='any',
                help='Change something',
                required=False)


args = parser.parse_args()
parser.print_help()

给出了:

usage: PROG [-h] [--infile File] [--outfile File]
            [--whatever-arg WHATEVER_ARG]

optional arguments:
  -h, --help            show this help message and exit
  --infile File, -i File
                        The input file/stream. (default: <open file '<stdin>',
                        mode 'r' at 0x10028e0c0>)
  --outfile File, -o File
                        The output file/stream. (default: <open file
                        '<stdout>', mode 'w' at 0x10028e150>)
  --whatever-arg WHATEVER_ARG, -w WHATEVER_ARG
                        Change something (default: any)

2 个答案:

答案 0 :(得分:6)

您可以将ArgumentDefaultsHelpFormatter子类化为您想要的。

from argparse import ArgumentDefaultsHelpFormatter,RawDescriptionHelpFormatter

class CustomFormatter(argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter):
    def _get_help_string(self, action):
        help = action.help
        if '%(default)' not in action.help:
            if action.default is not argparse.SUPPRESS:
                defaulting_nargs = [argparse.OPTIONAL, argparse.ZERO_OR_MORE]
                if action.option_strings or action.nargs in defaulting_nargs:
                    if type(action.default) == type(sys.stdin):
                        print action.default.name
                        help += ' (default: ' + str(action.default.name) + ')'
                    else:
                        help += ' (default: %(default)s)'
        return help

parser = argparse.ArgumentParser(prog='PROG', formatter_class=CustomFormatter)

我的结果是:

optional arguments:
  -h, --help            show this help message and exit
  --infile File, -i File
                        The input file/stream. (default: <stdin>)
  --outfile File, -o File
                        The output file/stream. (default: <stdout>)
  --whatever-arg WHATEVER_ARG, -w WHATEVER_ARG
                        Change something (default: any)

答案 1 :(得分:2)

如果您提供default='-'而不是sys.stdin,则帮助显示为

the input file/stream. (default: -)

也就是说,help显示默认字符串,但FileType'-'转换为stdin / out。

正如A.H所示,您可以自定义_get_help_string方法。您继承哪个类并不重要,因为修改该方法就是ADHF所做的全部:

class ArgumentDefaultsHelpFormatter(HelpFormatter):
    """...
    """
    def _get_help_string(self, action):
        help = action.help
        if '%(default)' not in action.help:
            if action.default is not SUPPRESS:
                defaulting_nargs = [OPTIONAL, ZERO_OR_MORE]
                if action.option_strings or action.nargs in defaulting_nargs:
                    help += ' (default: %(default)s)'
        return help

请注意,所有这些修改都会在help参数中添加一个字符串 - 只是(default: %(default)s)

这意味着您可以通过调整自己的help行来获得类似的效果,例如

parser.add_argument('--infile',
                '-i',
                metavar='File',
                help='The input file/stream, (default: stdin).',
                default='-',
                type=argparse.FileType('r'))

parser.add_argument('--whatever-arg',
                '-w',
                default='any',
                help='Change something, (default: %(default)s)')

换句话说,它可以节省您为28个参数键入(default: %(default)s)

如果你感到不舒服定制HelpFormatter类(虽然那是什么的开发者推荐 - 用合适的注意事项),你可以调整你自己的设置。例如,使用简单的辅助函数将额外的字符串添加到每个帮助行:

def foohelp(astr):
    return astr + ' (default: %(default)s)'

arg1 = parser.add_argument('-f','--fooarg', help=foohelp('help string'))

说到以编程方式更改设置,值得注意的是add_argument创建了一个Action对象。您可以像我在这里一样保存链接,并调整参数。

arg1 = parser.add_argument('-f','--fooarg', help='help string')
print arg1.help
arg1.help = foohelp(arg1.help)  # modify help after creation
print arg1.help

使用30个参数,您可能已经进行了大量的copy-n-paste来定义它们,或者编写各种辅助函数来简化设置。添加默认显示只是这些任务中的另一个。您可以在安装过程中执行此操作,也可以通过自定义格式化程序执行此操作。