'How can I require my python script's argument to be a float in a range using argparse?
I'd like to use argparse
on Python 2.7 to require that one of my script's parameters be between the range of 0.0 and 1.0. Does argparse.add_argument()
support this?
Solution 1:[1]
The type
parameter to add_argument
just needs to be a callable object that takes a string and returns a converted value. You can write a wrapper around float
that checks its value and raises an error if it is out of range.
def restricted_float(x):
try:
x = float(x)
except ValueError:
raise argparse.ArgumentTypeError("%r not a floating-point literal" % (x,))
if x < 0.0 or x > 1.0:
raise argparse.ArgumentTypeError("%r not in range [0.0, 1.0]"%(x,))
return x
p = argparse.ArgumentParser()
p.add_argument("--arg", type=restricted_float)
Solution 2:[2]
Here is a method that uses the choices
parameter to add_argument
, with a custom class that is considered "equal" to any float within the specified range:
import argparse
class Range(object):
def __init__(self, start, end):
self.start = start
self.end = end
def __eq__(self, other):
return self.start <= other <= self.end
parser = argparse.ArgumentParser()
parser.add_argument('--foo', type=float, choices=[Range(0.0, 1.0)])
Solution 3:[3]
Adding str makes that the boundaries are visuable in the help.
import argparse
class Range(object):
def __init__(self, start, end):
self.start = start
self.end = end
def __eq__(self, other):
return self.start <= other <= self.end
def __contains__(self, item):
return self.__eq__(item)
def __iter__(self):
yield self
def __str__(self):
return '[{0},{1}]'.format(self.start, self.end)
parser = argparse.ArgumentParser()
parser.add_argument('--foo', type=float, choices=Range(0.0, 1.0))
parser.add_argument('--bar', type=float, choices=[Range(0.0, 1.0), Range(2.0,3.0)])
Solution 4:[4]
The argparse.add_argument call expects an iterable as 'choices' parameter. So what about adding the iterable property to the Range class above. So both scenarios could be used:
import argparse
class Range(object):
def __init__(self, start, end):
self.start = start
self.end = end
def __eq__(self, other):
return self.start <= other <= self.end
def __contains__(self, item):
return self.__eq__(item)
def __iter__(self):
yield self
parser = argparse.ArgumentParser()
parser.add_argument('--foo', type=float, choices=Range(0.0, 1.0))
parser.add_argument('--bar', type=float, choices=[Range(0.0, 1.0), Range(2.0,3.0)])
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Andrew Clark |
Solution 3 | Bob Baeck |
Solution 4 | André Müller |