我应该在Python中针对坏/非法参数组合提出哪个例外?

时间:2008-11-01 23:02:37

标签: python exception arguments

我想知道在Python中指示无效参数组合的最佳实践。我遇到过一些你有这样功能的情况:

def import_to_orm(name, save=False, recurse=False):
    """
    :param name: Name of some external entity to import.
    :param save: Save the ORM object before returning.
    :param recurse: Attempt to import associated objects as well. Because you
        need the original object to have a key to relate to, save must be
        `True` for recurse to be `True`.
    :raise BadValueError: If `recurse and not save`.
    :return: The ORM object.
    """
    pass

唯一令人烦恼的是,每个包都有自己的,通常略有不同的BadValueError。我知道在Java中存在java.lang.IllegalArgumentException - 是否很好理解每个人都将在Python中创建自己的BadValueError或者是否有另一种首选方法?

8 个答案:

答案 0 :(得分:492)

我会提出ValueError,除非您需要更具体的例外情况。

def import_to_orm(name, save=False, recurse=False):
    if recurse and not save:
        raise ValueError("save must be True if recurse is True")

执行class BadValueError(ValueError):pass毫无意义 - 您的自定义类与ValueError的使用完全相同,为什么不使用它?

答案 1 :(得分:88)

我会继承ValueError

class IllegalArgumentError(ValueError):
    pass

创建自己的异常有时会更好,但是从内置的异常继承,尽可能接近你想要的。

如果您需要捕获该特定错误,请输入名称。

答案 2 :(得分:10)

我认为处理此问题的最佳方法是python本身处理它的方法。 Python引发TypeError。例如:

$ python -c 'print(sum())'
Traceback (most recent call last):
File "<string>", line 1, in <module>
TypeError: sum expected at least 1 arguments, got 0

我们的初级开发人员刚刚在Google搜索中找到了“ python异常错误参数”页面,而令我惊讶的是,自问这个问题以来的十年中,从未出现过明显的(对我而言)答案。

答案 3 :(得分:9)

我大多只看到在这种情况下使用的内置ValueError

答案 4 :(得分:1)

我不确定我同意来自ValueError的继承 - 我对文档的解释是ValueError 应该由内置提升...从中继承或自己提升它似乎是错误的。

  

内置操作时引发或   函数接收有一个参数   正确的类型但不合适   价值,情况不是   由更精确的例外描述   例如IndexError。

- ValueError documentation

答案 5 :(得分:1)

这取决于参数的问题。

如果参数的类型错误,则引发TypeError。例如,当您获取字符串而不是这些布尔值之一时。

if not isinstance(save, bool):
    raise TypeError(f"Argument save must be of type bool, not {type(save)}")

但是请注意,在Python中我们很少进行这样的检查。如果参数确实无效,那么一些更深层的功能可能会为我们带来麻烦。而且,如果我们仅检查布尔值,也许某些代码用户以后会向其提供一个字符串,因为它知道非空字符串始终为True。可能会帮他省下一个演员。

如果参数具有无效值,请引发ValueError。在您的情况下,这似乎更合适:

if recurse and not save:
    raise ValueError("If recurse is True, save should be True too")

或者在此特定情况下,具有递归的True值表示保存的True值。由于我认为这是从错误中恢复过来的,因此您可能还希望在日志中抱怨。

if recurse and not save:
    logging.warning("Bad arguments in import_to_orm() - if recurse is True, so should save be")
    save = True

答案 6 :(得分:0)

同意Markus&#39;建议滚动自己的异常,但异常的文本应该澄清问题在参数列表中,而不是单个参数值。我建议:

class BadCallError(ValueError):
    pass

在缺少特定调用所需的关键字参数时使用,或者参数值单独有效但彼此不一致。当特定参数类型正确但超出范围时,ValueError仍然是正确的。

这不应该是Python中的标准异常吗?

一般来说,我喜欢Python风格,以便将错误的输入与函数(调用者的错误)区分开来,以及函数内的错误结果(我的错)。因此,可能还有BadArgumentError来区分参数中的值错误和本地值中的值错误。

答案 7 :(得分:0)

在这种情况下,您很可能会使用 ValueError(完整的raise ValueError()),但这取决于错误值的类型。例如,如果你创建了一个只允许字符串的函数,而用户输入的是一个整数,你会用 TypeError 代替。如果用户输入了错误的输入(意味着它具有正确的类型但不符合某些条件),Value Error 将是您的最佳选择。 Value Error 也可用于阻止程序发生其他异常,例如,您可以使用 ValueError 来阻止 shell 表单引发 ZeroDivisionError,例如,在此函数中:

def function(number):
    if not type(number) == int and not type(number) == float:
        raise TypeError("number must be an integer or float")
    if number == 5:
        raise ValueError("number must not be 5")
    else:
        return 10/(5-number)

附言有关 Python 内置异常的列表,请转到此处: https://docs.python.org/3/library/exceptions.html(这是官方的python数据库)