标题基本上概括了我希望发生的事情。
这是我所拥有的,虽然程序不会在非正整数上出错,但我希望用户知道,非正整数基本上是没有意义的。
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-g", "--games", type=int, default=162,
help="The number of games to simulate")
args = parser.parse_args()
输出:
python simulate_many.py -g 20
Setting up...
Playing games...
....................
输出负号:
python simulate_many.py -g -2
Setting up...
Playing games...
显然,我可以添加一个if来确定if参数。games是负的,但我很好奇是否有一种方法可以在argparse级别捕获它,以便利用自动使用打印。
理想情况下,它会打印类似这样的东西:
python simulate_many.py -g a
usage: simulate_many.py [-h] [-g GAMES] [-d] [-l LEAGUE]
simulate_many.py: error: argument -g/--games: invalid int value: 'a'
像这样:
python simulate_many.py -g -2
usage: simulate_many.py [-h] [-g GAMES] [-d] [-l LEAGUE]
simulate_many.py: error: argument -g/--games: invalid positive int value: '-2'
现在我这样做了,我想我很高兴:
if args.games <= 0:
parser.print_help()
print "-g/--games: must be positive."
sys.exit(1)
如果有人(像我一样)在谷歌搜索中遇到这个问题,这里有一个如何使用模块化方法巧妙地解决更普遍的问题,只允许argparse整数在指定的范围内:
# Custom argparse type representing a bounded int
class IntRange:
def __init__(self, imin=None, imax=None):
self.imin = imin
self.imax = imax
def __call__(self, arg):
try:
value = int(arg)
except ValueError:
raise self.exception()
if (self.imin is not None and value < self.imin) or (self.imax is not None and value > self.imax):
raise self.exception()
return value
def exception(self):
if self.imin is not None and self.imax is not None:
return argparse.ArgumentTypeError(f"Must be an integer in the range [{self.imin}, {self.imax}]")
elif self.imin is not None:
return argparse.ArgumentTypeError(f"Must be an integer >= {self.imin}")
elif self.imax is not None:
return argparse.ArgumentTypeError(f"Must be an integer <= {self.imax}")
else:
return argparse.ArgumentTypeError("Must be an integer")
这允许你做一些类似的事情:
parser = argparse.ArgumentParser(...)
parser.add_argument('foo', type=IntRange(1)) # Must have foo >= 1
parser.add_argument('bar', type=IntRange(1, 7)) # Must have 1 <= bar <= 7
变量foo现在只允许正整数,就像OP要求的那样。
注意,除了上面的表单外,IntRange也可以只使用maximum:
parser.add_argument('other', type=IntRange(imax=10)) # Must have other <= 10
如果有人(像我一样)在谷歌搜索中遇到这个问题,这里有一个如何使用模块化方法巧妙地解决更普遍的问题,只允许argparse整数在指定的范围内:
# Custom argparse type representing a bounded int
class IntRange:
def __init__(self, imin=None, imax=None):
self.imin = imin
self.imax = imax
def __call__(self, arg):
try:
value = int(arg)
except ValueError:
raise self.exception()
if (self.imin is not None and value < self.imin) or (self.imax is not None and value > self.imax):
raise self.exception()
return value
def exception(self):
if self.imin is not None and self.imax is not None:
return argparse.ArgumentTypeError(f"Must be an integer in the range [{self.imin}, {self.imax}]")
elif self.imin is not None:
return argparse.ArgumentTypeError(f"Must be an integer >= {self.imin}")
elif self.imax is not None:
return argparse.ArgumentTypeError(f"Must be an integer <= {self.imax}")
else:
return argparse.ArgumentTypeError("Must be an integer")
这允许你做一些类似的事情:
parser = argparse.ArgumentParser(...)
parser.add_argument('foo', type=IntRange(1)) # Must have foo >= 1
parser.add_argument('bar', type=IntRange(1, 7)) # Must have 1 <= bar <= 7
变量foo现在只允许正整数,就像OP要求的那样。
注意,除了上面的表单外,IntRange也可以只使用maximum:
parser.add_argument('other', type=IntRange(imax=10)) # Must have other <= 10
一个更简单的替代方案,特别是在继承argparse的子类时。ArgumentParser,是从parse_args方法内部启动验证。
在这样的子类中:
def parse_args(self, args=None, namespace=None):
"""Parse and validate args."""
namespace = super().parse_args(args, namespace)
if namespace.games <= 0:
raise self.error('The number of games must be a positive integer.')
return namespace
这种技术可能不像自定义可调用对象那么酷,但它可以完成任务。
关于ArgumentParser.error(信息):
该方法打印一条使用消息,其中包含标准错误的消息,并使用状态码2终止程序。
来源:jonatan回答