在Python中使用'argparse.ArgumentError'

我想在Python的 argparse 模块中使用 ArgumentError 异常,但我无法弄清楚如何使用它。签名说它应该被称为 ArgumentError(参数,消息),但我无法弄清楚参数应该是什么。我认为它应该是解析器对象的一部分,但我找不到任何文档。

35
您可以在自定义 Action 类中使用它,就像现有类一样。但我无法想象在解析器之外这样做的理由。它没有任何特殊之处 - 只需将 Action 名称添加到错误消息中即可。研究它在代码中的用法。
额外 作者 hpaulj,
额外 作者 DavidRR,

2 答案

源文档

ArgumentError:当解析器的操作出错时,ArgumentParser对象引发的异常。解析命令行时引发的错误被ArgumentParser捕获并作为命令行消息发出。

构造函数的参数参数是引发异常的 Action 对象。通常不需要在 Action 子类之外引出它,并且在对它进行子类化时,不需要显式地引出它;你通常会提出 ValueError (或其他任何合适的东西)。

浮点值介于0和1之间

关于您的注释,您只想接受介于0和1之间的浮点值。为此,您应该使用定义自定义类型的功能。你可以这样做,例如:

def percentFloat (string):
    value = float(string)
    if value < 0 or value > 1:
        raise argparse.ArgumentTypeError('Value has to be between 0 and 1')
    return value

parser = argparse.ArgumentParser()
parser.add_argument('test', type=percentFloat)
parser.parse_args()

请注意,这对非浮点数也是安全的,因为 float(string)将为非浮点引发 ValueError ,这也会通过 argparse触发无效类型错误模块。 ArgumentTypeError 只是一种指定方式自定义错误消息。

互斥参数

For 互斥参数, you should use argparse.add_mutually_exclusive_group.

参数依赖

参数依赖 isn’t really something that should be done by the argument parser. For semantic details, you should instead simply do it yourself:

args = parser.parse_args()
if args.w and not args.p:
    parser.error('-p is required when -w is set.')

您可以使用 ArgumentParser.error 来提升自定义错误消息将中断程序并打印到控制台。

但是当然在这种基本情况下,如果可能的话,隐含地猜测 -p 会更有意义。

49
额外
那是不对的。如果我只是发送值,我得 AttributeError:'float'对象没有属性'option_strings'
额外 作者 asmeurer,
顺便说一句,我想使用它,因为我想进行类型检查,模块不直接支持。例如,我想要一个介于0和1之间的浮点值.argparse允许您指定它应该是一个浮点数,但我必须手动检查范围。这似乎是值错误时发出的正确错误。
额外 作者 asmeurer,
downvote是因为答案是错误的。如上所述,ArgumentError(1.1,“Value out of range”)引发了AttributeError。这需要是某种内部argparse对象,但我无法弄清楚是什么。顺便说一下,另一个你可能想要这样做的例子是你想要定义一个非平凡的参数依赖,据我所知,argparse模块不直接支持。类似 -w 选项的东西需要 -p 选项,或者 -n-N 是互斥的。
额外 作者 asmeurer,
谢谢。那个parser.error就是我想要的。
额外 作者 asmeurer,
@asmeurer编辑我的答案给你一个如何做到这一点的例子。
额外 作者 poke,
更新了我的回答。
额外 作者 poke,

虽然 parser.error()是大多数人可能想要的,但也可以使用argparse.ArgumentError()(如问题所示)。你需要引用参数,比如 bar_arg

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--foo')
bar_arg = parser.add_argument('--bar')

args = parser.parse_args()
if args.bar == 'xyzzy':
    raise argparse.ArgumentError(bar_arg, "Can't be 'xyzzy'")

if args.foo == 'xyzzy':
    parser.error("Can't be 'xyzzy'")

这将产生如下输出:

$ python argparse_test.py --foo xyzzy
usage: argparse_test.py [-h] [--foo FOO] [--bar BAR]
argparse_test.py: error: Can't be 'xyzzy'

$ python argparse_test.py --bar xyzzy
Traceback (most recent call last):
  File "argparse_test.py", line 10, in 
    raise argparse.ArgumentError(bar_arg, "Can't be 'xyzzy'")
argparse.ArgumentError: argument --bar: Can't be 'xyzzy'
11
额外
这是一个很好的例子,说明如何在 parser 之外使用 ArgumentError ,但可能不如使用 parser.error
额外 作者 hpaulj,
好吧,如果你写好错误信息,那么你一定要提及哪个开关是违规的。为每个添加的参数创建单独的变量可能非常麻烦......
额外 作者 Praveen,
@hpaulj,是的,但是ArgumentError有一个好处:它可以让你知道哪个开关是有问题的。
额外 作者 ukrutt,
@Praveen我想这是一个偏好问题。我自己更喜欢变量写'' - foo'不能'xyzzy'“,因为我必须记住开关的正确名称(它不一定与 args的属性相同) </代码>)。但老实说,我认为 parser.error()默认情况下应该包含违规交换机的名称。
额外 作者 ukrutt,