什么是处理异常的首选方法?

时间:2016-02-29 08:01:07

标签: python exception zen-of-python

如果我在编写代码时不确定,我会再次尝试阅读The Zen of Python。这一次,这些线条让我犹豫不决。

Errors should never pass silently.
Unless explicitly silenced.

在当前代码中,我有一些可能看起来像这样的函数:

def add_v_1(a, b):
    return a + b 

所有对他们的要求都是:

c = add_v_1(7, [])

此类代码的异常将冒出并在上层捕获。

但它应该是这样吗?

add_v_1可能会引发TypeError异常,我想从中恢复。 因此,可能的函数调用是:

try:
    c = add_v_1(7, [])
except TypeError:
    print "Incorrect types!"

但对于每次通话,我都应该进行异常处理。这看起来很重。

所以,我可以这样做:

def add_v_2(a, b):
    try:
        return a + b
    except TypeError:
        print "Incorrect types!"

并打电话:

c = add_v_2(7, [])

看起来更干净。

似乎所有这些方法都遵循The Zen of Python,但其中哪一种是更好的选择?

3 个答案:

答案 0 :(得分:3)

参考你的例子,你是否应该在函数内捕获异常是有争议的。这样做会从函数返回None,然后通过检查函数的返回值来加重调用代码,并将None视为错误。它通过错误检查有效地替换了异常处理。前者通常更像Pythonic。

您应该询问是否有必要捕获错误,例如尝试添加2个完全不同的数据类型。在这种情况下这样做似乎是一个编程错误,而不是在正常执行期间你期望的事情。

你能做些什么来处理这样的错误?似乎没有任何有用的值可以在函数的预期输出的域内返回...除了None以外,表示无法生成结果。但是调用代码仍然必须执行某种错误检查...所以它也可以只处理异常 - 至少它只需处理一次。

但这个例子是人为的,很难给出全面的建议。在这种特殊情况下,由于上述原因,我会允许异常传播到调用代码并在那里处理它。

答案 1 :(得分:2)

当你能够从中恢复时,你应该处理。如果您尝试添加两个具有不兼容类型的值,则无法从中恢复(没有进一步的上下文)。

让我们假设您编写了一个IntegerWrapper类和您的函数" add_v_2"通常应该尝试连接两个值。

def add_v_2(a, b):
    try:
        return a + b
    except TypeError as e:
        if isinstance(a, IntegerWrapper):
            return str(a) + b
        else:
            print("I dont know how to handle this type: " + type(a).__name__)
            # reraise the error so the caller can handle it
            raise

这会尝试从a恢复"错误类型",但是如果您知道如何从中恢复。如果它不知道(a是另一种类型)它会重新引用异常,所以知道如何处理它的人会看到错误。

(当然,该实现包含错误,它并不意味着是一个良好的实现")

答案 2 :(得分:0)

输入:

def add_v_2(a, b):
    try:
        return a + b
    except Exception as e:
        print str(e)
c = add_v_2(7, [])
print (c)

输出:

unsupported operand type(s) for +: 'int' and 'list'
None