Python argparse 值范围帮助信息显示

19 投票
5 回答
24534 浏览
提问于 2025-04-18 17:12

我有一个程序的参数,它是一个从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)

5 个回答

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

其他功能包括:

  • 能够一致地处理 default(默认值)、metavar(变量名)和 nargs(参数个数),和默认的 argparse 处理方式相同
  • 类型推断,可以通过 type 参数来明确覆盖
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

使用自定义的 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)
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.
33

使用 metavar 参数add_argument() 函数中。

举个例子:

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.

撰写回答