Python argparse 值范围帮助消息外观

19

我有一个程序的参数,是从1到100的整数,但我不喜欢使用argparse时在-h帮助消息中呈现的方式(它会列出0、1、2、3、4、5等等)。

是否有任何方法可以更改此方式或以另一种方式表示它?

谢谢

编辑:

以下是那些要求的代码:

norse = parser.add_argument_group('Norse')
norse.add_argument('-n', '--norse', required=False, help='Run the Norse IPViking scan.', action='store_true')
norse.add_argument('--threshold', required=False, type=int, choices=range(0,101), help='Threshold (0-100) denoting at what threat level to provide additional data on an IP \
                        address. Default is 49.', default=49)

你能发一下你的代码示例吗? - OldGeeksGuide
API没有提供任何建议,也许你可以实现自己的检查,而不是使用选择。 - Pankaj Sharma
你可以尝试查看argparse.ArgumentDefaultsHelpFormatter,我自己没有使用过它,但它可能提供你所需的定制化功能。 - OldGeeksGuide
是的,我在考虑放弃内置检查并运行自己的检查,但如果我能在argparse中保留它就更好了...哦,算了。 - DJMcCarthy12
5个回答

32
< p > 使用 add_argument()metavar 参数。

例如:

norse = parser.add_argument_group('Norse')
norse.add_argument('-n', '--norse', required=False, help='Run the Norse IPViking scan.', action='store_true')
norse.add_argument('--threshold', required=False, type=int, choices=range(0,101),
                   metavar="[0-100]", 
                   help='Threshold (0-100) denoting at what threat level to provide additional data on an IP \
                        address. Default is 49.', default=49)

测试:

from argparse import ArgumentParser

norse = ArgumentParser()

norse.add_argument('-n', '--norse', required=False, help='Run the Norse IPViking scan.', action='store_true')
norse.add_argument('--threshold', required=False, type=int, choices=range(0,101), metavar="[0-100]", help='Threshold (0-100) denoting at what threat level to provide additional data on an IP address. Default is 49.', default=49)


norse.print_help()

结果

usage: -c [-h] [-n] [--threshold [0-100]]

optional arguments:
  -h, --help           show this help message and exit
  -n, --norse          Run the Norse IPViking scan.
  --threshold [0-100]  Threshold (0-100) denoting at what threat level to
                       provide additional data on an IP address. Default is
                       49.

8
metavar用于usagehelp,但不能帮助处理错误信息。更多详情请参见http://bugs.python.org/issue16418和http://bugs.python.org/issue16468。 - hpaulj
@hpaulj 感谢您提供的参考资料。这非常有趣。 - Xin Yin

8

您可以自定义操作,例如:

#!/usr/bin/env python
import argparse


class Range(argparse.Action):
    def __init__(self, minimum=None, maximum=None, *args, **kwargs):
        self.min = minimum
        self.max = maximum
        kwargs["metavar"] = "[%d-%d]" % (self.min, self.max)
        super(Range, self).__init__(*args, **kwargs)

    def __call__(self, parser, namespace, value, option_string=None):
        if not (self.min <= value <= self.max):
            msg = 'invalid choice: %r (choose from [%d-%d])' % \
                (value, self.min, self.max)
            raise argparse.ArgumentError(self, msg)
        setattr(namespace, self.dest, value)


norse = argparse.ArgumentParser('Norse')
norse.add_argument('--threshold', required=False, type=int, min=0, max=100,
                   action=Range,
                   help='Threshold [%(min)d-%(max)d] denoting at what threat \
                         level to provide additional data on an IP address. \
                         Default is %(default)s.', default=49)
args = norse.parse_args()
print args

测试它:

~: user$ ./test.py --threshold 10
Namespace(threshold=10)
~: user$ ./test.py --threshold -1
usage: Norse [-h] [--threshold [0-100]]
Norse: error: argument --threshold: invalid choice: -1 (choose from [0-100])
~: user$ ./test.py -h
usage: Norse [-h] [--threshold [0-100]]

optional arguments:
  -h, --help           show this help message and exit
  --threshold [0-100]  Threshold [0-100] denoting at what threat level to
                       provide additional data on an IP address. Default is
                       49.

3
我会将“类型”进行定制,而不是“动作”。 - hpaulj

8
使用自定义的 type,可以更容易地控制错误消息(通过 ArgumentTypeError)。但仍需要 metavar 来控制使用显示。
import argparse

def range_type(astr, min=0, max=101):
    value = int(astr)
    if min<= value <= max:
        return value
    else:
        raise argparse.ArgumentTypeError('value not in range %s-%s'%(min,max))

parser = argparse.ArgumentParser()
norse = parser.add_argument_group('Norse')
...
norse.add_argument('--range', type=range_type, 
    help='Value in range: Default is %(default)s.',
    default=49, metavar='[0-101]')
parser.print_help()
print parser.parse_args()

生成:

2244:~/mypy$ python2.7 stack25295487.py --ran 102
usage: stack25295487.py [-h] [-n] [--threshold [0:101]] [--range [0-101]]

optional arguments:
  -h, --help           show this help message and exit

Norse:
  ...
  --range [0-101]      Value in range: Default is 49.
usage: stack25295487.py [-h] [-n] [--threshold [0:101]] [--range [0-101]]
stack25295487.py: error: argument --range: value not in range 0-101

我可以使用 functools.partial 来自定义范围值:
type=partial(range_type, min=10, max=90)

2
以下是几种替代方法。
def parseCommandArgs():
    parser = argparse.ArgumentParser()
    parser.add_argument('-i', dest='myDest', choices=range(1,101), type=int, required=True, metavar='INT[1,100]', help='my help message')
    return parser.parse_args()

你也可以使用action,我强烈推荐这种方法,因为它允许更多的自定义。

def verify():
    class Validity(argparse.Action):
        def __call__(self, parser, namespace, values, option_string=None):
            if values < 1 or values > 100:
                # do something
                pass
    return Validity

def parseCommandArgs():
    parser = argparse.ArgumentParser()
    parser.add_argument('-i', dest='myDest', required=True, metavar='INT[1,100]', help='my help message', action=verify())
    return parser.parse_args()

谢谢!8年后,您的metavar建议帮助我解决了类似的问题,其中argparse在帮助消息中打印了所有约65k个端口号。 - Seaver

0
我已经为此编写了一个库:argparse-range
>>> from argparse import ArgumentParser
>>> from argparse_range import range_action
>>> parser = ArgumentParser()
>>> parser.add_argument("rangedarg", action=range_action(0, 10), help="An argument")
>>> args = parser.parse_args(["0"])
>>> args.rangedarg
0
>>> parser.parse_args(["20"])
Traceback (most recent call last):
    ....
argparse.ArgumentTypeError: Invalid choice: 20 (must be in range 0..=10)

帮助文本被透明地添加:

foo.py --help

usage: foo.py [-h] rangedarg

positional arguments:
  rangedarg   An argument (must be in range 0..=10)

optional arguments:
  -h, --help  show this help message and exit

其他功能包括:
  • 与默认argparse处理一致地处理default、metavar和nargs
  • 类型推断,可使用"type"参数明确覆盖

当链接到您自己的网站或内容(或与之有关联的内容)时,为了不被视为垃圾邮件,您必须在答案中披露您的从属关系。在用户名中具有相同的文本作为网址或在个人资料中提及它在Stack Exchange政策下被认为不足以构成充分的披露。 - cigien

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