8

根据有关异常的成语和反成语的 Python 文档:“您应该尝试在代码中使用尽可能少的 except 子句——您使用的子句通常是内部调用,应该总是成功,或者在一个主要功能中包罗万象。” 把这句话分段...

“你应该尽量在你的代码中使用尽可能少的 except 子句”

对于像我这样的新手来说有点困惑,我认为在 Python 中使用EAFP样式是一种很好的做法——即许多tryexcept语句。还是我错过了重点?

“您使用的通常是内部调用,应该总是成功”

我不明白这里所说的意思。

“或者是一个主要功能中的一个包罗万象的东西。”

因此,对于任何抛出异常的 let 代码来说,将其简单地传递到调用堆栈直到它到达您真正具有通用异常处理的顶层是一种很好的风格?

4

4 回答 4

2

“你应该尽量在你的代码中使用尽可能少的 except 子句”

很容易在代码中乱扔异常:

def solve_linear(mat1, mat2):
    det1 = determinant(mat1)
    det2 = determinant(mat2)
    try:
        return det1 / det2
    except ZeroDivisionError:
        raise NoSolution

在这里,让ZeroDivisionError传播可能很好。你不需要抓住它。

“您使用的通常是内部调用,应该总是成功”

例如,看看这个读取文件或返回缓存值的代码。它通常会成功,尽管有KeyError例外:

def read_file(path):
    try:
        return cache[path]
    except KeyError:
        fp = open(path, 'rb')
        data = fp.read()
        fp.close()
        cache[path] = data
        return data

“或者是一个主要功能中的一个包罗万象的东西。”

如果您的程序是交互式的,您可能希望在顶层捕获几乎所有内容。这是交互式命令行程序的顶部循环:

def main():
    while True:
        try:
            text = raw_input('enter command: ')
            cmd = parse_command(text)
        except EOFError:
            return
        except KeyboardInterrupt:
            return
        except ValueError:
            print 'Syntax error'
            continue

        try:
            run_cmd(cmd)
        except SystemExit:
            raise
        except Exception:
            traceback.print_exc()
于 2012-10-25T17:48:05.960 回答
1

我认为关键是例外应该只用于“例外”情况。这就是使用“在通常会成功的调用中”背后的含义。这方面的一个例子可能是一些计算,在一些非常奇怪的情况下,最终不得不除以零。然后,您可以将其包含在 try / except 语句中以处理这种可能性。

main 函数中的包罗万象将适用于相同的场景。假设您的计算最终在调用堆栈深处某处除以零。从这一点开始,您将无法继续,因此在失败时使用 try/except 语句是没有意义的。只在更高级别设置一个更有意义,您可以合理地从错误中恢复。

他们在文档中给出的例子就是一个例子。调用“get_status”时,您希望该文件存在。如果没有,那么您可以使用 except 语句来处理它(尽管如前所述,在这种特殊情况下,'with' 语句要好得多)。

于 2012-10-25T17:36:22.173 回答
1

关于第一点,使用异常的全部意义在于您不必将每一行都包装成一个!例如,在 C 中,错误通常由函数调用的返回值决定。因此,如果您想捕获所有错误,则必须在每次通话后检查这些内容。使用 Python,您可以将一个(可能很大)语句块组合在一个 try/except 块中,并且只处理一次所有错误。

第二点是(如果可能的话)您希望在故障发生点附近解决故障。例如,您正在从网络读取数据并获得零字节。在这种情况下,等待并重试通常是完全可以的。

最后一点是,有时错误太大以至于无法在低级别处理。例如,如果您试图打开一个不存在的文件,它将失败。而且您的程序无法对文件的内容执行任何操作。最好在程序的顶层处理它并询问用户另一个文件名或者退出程序。

于 2012-10-25T17:38:32.710 回答
1

Python 的哲学通常是“请求宽恕,而不是许可”。但这个想法不是使用 try-except 子句来捕获所有可能的错误。理想情况下,每个 try-except 只会捕获相关的错误。

BAD(未指定特定的异常类型):

a = [1, 2, 3]
i = 3
try:
    print a[i]
except:
    print "Not found!"

GOOD(只处理我们期望得到的异常):

a = [1, 2, 3]
i = 3
try:
    print a[i]
except IndexError:
    print "Not found!"

这很重要的原因是我们不会掩盖其他可能的代码错误。如果在这个例子中i是 1.8 怎么办?第一个示例会打印Not Found!,掩盖了真正的问题,但第二个示例会返回TypeError: list indices must be integers, not float,让我们知道我们的代码中存在逻辑缺陷。

于 2012-10-25T17:42:39.583 回答