[Tutor] using ranges with argparse()

Peter Otten __peter__ at web.de
Mon Jan 28 09:33:45 CET 2013


Kurt Lieber wrote:

> Hi -- brand new to python, but trying to write a simple script that takes
> command line arguments. One of the arguments needs to test if a value is
> a)
> an integer and b) within a stated range.  I currently have:
> 
> parser.add_argument("-f", "--floor", default=6000, help="floor is the
> minimum amount of bonus points.",type=int, choices=range(5995, 6001))
> 
> This works, but when the user enters an out of bounds value, the help
> message is unfriendly:
> 
> % ./bonus.py -f 10000
> usage: bonus.py [-h] [-f {5995,5996,5997,5998,5999,6000}]
> MAM-bonus.py: error: argument -f/--floor: invalid choice: 10000 (choose
> from 5995, 5996, 5997, 5998, 5999, 6000)
> 
> The problem is my default range is actually 0,10000 -- I changed it above
> for brevity's sake. So in the real world, it floods the screen to the
> point where it's unreadable.
> 
> I can suppress the whole thing with argparse.SUPPRESS, but then I'm left
> with no help message at all.  Is there a way to suppress the "(choose from
> 1,2,3,etc.)" part of the help message?  Or a cleaner/different way
> altogether to accomplish the same thing?

You can supply a custom function as the type to the add_argument() method:

http://docs.python.org/2/library/argparse.html#type

Here's a basic example:

$ cat argparse_intrange.py
import argparse

def check_range(arg):
    try:
        value = int(arg)
    except ValueError as err:
       raise argparse.ArgumentTypeError(str(err))

    if value < 0 or value > 10000:
        message = "Expected 0 <= value <= 10000, got value = {}".format(value)
        raise argparse.ArgumentTypeError(message)

    return value

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("alpha", type=check_range, nargs="?")

    print(parser.parse_args())

$ python argparse_intrange.py 
Namespace(alpha=None)
$ python argparse_intrange.py 100
Namespace(alpha=100)
$ python argparse_intrange.py -100
usage: argparse_intrange.py [-h] [alpha]
argparse_intrange.py: error: argument alpha: Expected 0 <= value <= 10000, got value = -100
$ python argparse_intrange.py 100000
usage: argparse_intrange.py [-h] [alpha]
argparse_intrange.py: error: argument alpha: Expected 0 <= value <= 10000, got value = 100000
$ python argparse_intrange.py x
usage: argparse_intrange.py [-h] [alpha]
argparse_intrange.py: error: argument alpha: invalid literal for int() with base 10: 'x'

If you want to use check_range() with arbitrary ranges you can parameterise it:

import functools

def check_range(arg, min, max):
    # your code

check_range_alpha = functools.partial(check_range, min=0, max=10000)
check_range_beta = functools.partial(check_range, min=-10, max=10)

parser = argparse.ArgumentParser()
parser.add_argument("alpha", type=check_range_alpha, nargs="?")
parser.add_argument("beta", type=check_range_beta, nargs="?")




More information about the Tutor mailing list