繁体   English   中英

对于 Python 中的错误/非法参数组合,我应该引发哪个异常?

[英]Which exception should I raise on bad/illegal argument combinations in Python?

我想知道在 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或者是否有另一种首选方法?

我只会提高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相同,那么为什么不使用它呢?

我会从ValueError继承

class IllegalArgumentError(ValueError):
    pass

有时最好创建自己的异常,但从内置异常继承,这尽可能接近您想要的。

如果您需要捕获该特定错误,拥有一个名称会很有帮助。

我认为处理这个问题的最好方法是 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

我们的初级开发人员刚刚在谷歌搜索“python 异常错误参数”中找到了这个页面,我很惊讶自问这个问题以来的十年里,没有人提出明显的(对我来说)答案。

这取决于参数的问题是什么。

如果参数的类型错误,则引发 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")

或者在这种特定情况下,递归的真值意味着保存的真值。 由于我认为这是从错误中恢复,您可能还想在日志中抱怨。

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

我主要只是看到在这种情况下使用的内置ValueError

在这种情况下,您很可能会使用ValueErrorraise ValueError() in full),但这取决于错误值的类型。 例如,如果您创建了一个只允许字符串的函数,而用户输入的是一个整数,那么您将使用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)

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

我不确定我是否同意从ValueError继承——我对文档的解释是ValueError应该由内置函数引发……从它继承或自己引发似乎不正确。

当内置操作或函数接收到类型正确但值不合适的参数时引发,并且这种情况没有用更精确的异常(如 IndexError)描述。

-- ValueError 文档

同意 Markus 的建议,推出您自己的例外,但例外的文本应阐明问题出在参数列表中,而不是单个参数值中。 我建议:

class BadCallError(ValueError):
    pass

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

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

一般来说,我希望 Python 风格在区分函数的错误输入(调用者的错误)和函数中的错误结果(我的错误)方面更加清晰。 所以也可能有一个 BadArgumentError 来区分参数中的值错误和局部变量中的值错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM