第七章 - 异常处理

当程序中发生错误时,您会怎么做?假设您试图打开一个文件,但是您输入了错误的路径,或者您向用户询问信息,他们输入了一些垃圾。您不希望程序崩溃,因此实现异常处理。在Python中,构造通常被称为 try/except .我们将在本章中讨论以下主题:

  • 常见异常类型

  • 处理异常 try/except

  • 了解如何 try/except/finally 作品

  • 了解 else 声明与 try/except

让我们从了解一些您将在Python中看到的最常见的异常开始。注意:当我们谈论异常处理时,一个错误和一个异常只是描述同一事物的不同词。

常见异常

你已经看到了一些例外。以下是最常见的内置异常列表(来自 Python documentation ):

  • 例外 (这几乎是所有其他建筑的基础)

  • AttributeError -当属性引用或赋值失败时引发。

  • IOError -当I/O操作(例如print语句、内置的open()函数或文件对象的方法)由于与I/O相关的原因(例如“找不到文件”或“磁盘已满”)失败时引发。

  • ImportError -当import语句找不到模块定义或 来自…进口 找不到要导入的名称。

  • IndexError -序列下标超出范围时引发。

  • KeyError -在现有键集中找不到映射(字典)键时引发。

  • KeyboardInterrupt -当用户点击中断键(通常为Control-C或Delete)时引发。

  • NameError -在找不到本地或全局名称时引发。

  • OSError -当函数返回与系统相关的错误时引发。

  • SyntaxError -在分析器遇到语法错误时引发。

  • TypeError -当操作或函数应用于不适当类型的对象时引发。关联值是一个字符串,提供有关类型不匹配的详细信息。

  • ValueError -当内置操作或函数接收到具有正确类型但值不正确的参数,并且该情况未由更精确的异常(如indexError)描述时引发。

  • ZeroDivisionError -当除法或模运算的第二个参数为零时引发。

还有很多其他的例外,但你可能不会经常看到它们。但是,如果您感兴趣,可以在 Python documentation .

如何处理异常

在Python中处理异常非常简单。让我们花点时间写一些会导致异常的例子。我们将从最常见的计算机科学问题之一开始:除以零。

>>> 1 / 0
Traceback (most recent call last):
    File "<string>", line 1, in <fragment>
ZeroDivisionError: integer division or modulo by zero

>>> try:
        1 / 0
    except ZeroDivisionError:
        print("You cannot divide by zero!")

You cannot divide by zero!

如果你回想一下初级数学课,你会记得你不能被零除。在python中,这个操作将导致一个错误,正如您在示例的前半部分中看到的那样。为了捕获错误,我们用 try/except 语句。


纯例外

以下是捕获错误的另一种方法:

>>> try:
        1 / 0
    except:
        print("You cannot divide by zero!")

这是 not 推荐!在python中,这被称为 光的,除了 这意味着它将捕获任何和所有异常。不建议这样做的原因是您不知道要捕获哪个异常。当你有类似的东西 除零分区错误外 ,显然您正试图捕获一个被零除的错误。在上面的代码中,您无法知道您试图捕获什么。


让我们看看其他几个例子。

>>> my_dict = {"a":1, "b":2, "c":3}
>>> try:
        value = my_dict["d"]
    except KeyError:
        print("That key does not exist!")

That key does not exist!
>>> my_list = [1, 2, 3, 4, 5]
>>> try:
        my_list[6]
    except IndexError:
        print("That index is not in the list!")

That index is not in the list!

在第一个示例中,我们创建一个3元素字典。然后我们尝试访问字典中没有的密钥。因为密钥不在字典中,所以它会引发 KeyError 我们抓住了。第二个示例显示了一个长度为5项的列表。我们试图从索引中获取第7项。记住,python列表是基于零的,所以当你说 [6] 你要的是第七件。不管怎样,因为只有5个项目,它会引发一个 IndexError 我们也能抓住。

您还可以用一条语句捕获多个异常。有几种不同的方法可以做到这一点。让我们看看:

my_dict = {"a":1, "b":2, "c":3}
try:
    value = my_dict["d"]
except IndexError:
    print("This index does not exist!")
except KeyError:
    print("This key is not in the dictionary!")
except:
    print("Some other error occurred!")

这是捕获多个异常的相当标准的方法。首先,我们尝试访问字典中不存在的密钥。“Try/Except”检查是否捕捉到一个键错误,该错误在第二个键中 except 声明。你也会注意到,我们有一个空的,除了最后。通常不建议这样做,但您可能会不时看到它,因此了解它是件好事。还要注意,大多数情况下,您不需要将一块代码包装成多个 except 处理程序。你通常只需要把它包起来。

下面是捕获多个异常的另一种方法:

try:
    value = my_dict["d"]
except (IndexError, KeyError):
    print("An IndexError or KeyError occurred!")

注意,在这个例子中,我们将要捕获的错误放在括号内。这个方法的问题是很难判断实际发生了哪个错误,所以推荐前面的例子。

大多数情况下,当发生异常时,您需要通过打印到屏幕或记录消息来提醒用户。根据错误的严重性,您可能需要退出程序。有时,在退出程序之前,您需要进行清理。例如,如果您打开了一个数据库连接,您将希望在退出程序之前关闭它,否则您可能会使连接保持打开状态。另一个例子是关闭您一直在写入的文件句柄。您将在下一章中了解有关文件处理的更多信息。但首先,我们需要学会如何清理自己。这是通过 finally 语句。

最后的陈述

这个 finally 语句真的很容易使用。让我们来看一个愚蠢的例子:

my_dict = {"a":1, "b":2, "c":3}

try:
    value = my_dict["d"]
except KeyError:
    print("A KeyError occurred!")
finally:
    print("The finally statement has executed!")

如果运行上面的代码,它将在 except 以及 finally .这很简单,对吧?现在您可以使用 finally 为自己清理的声明。您还可以将退出代码放在 finally 语句。

try, except, or else!

这个 try/except 语句还具有 else 条款。这个 else 仅在没有引发错误时运行。我们将花一些时间来看看几个例子:

my_dict = {"a":1, "b":2, "c":3}

try:
    value = my_dict["a"]
except KeyError:
    print("A KeyError occurred!")
else:
    print("No error occurred!")

这里我们有一本字典,里面有3个元素 try/except 我们访问一个存在的密钥。这是可行的,所以 KeyErrornot 提高。因为没有错误, else 执行并“未发生错误!”打印到屏幕上。现在让我们加入 finally 声明:

my_dict = {"a":1, "b":2, "c":3}

try:
    value = my_dict["a"]
except KeyError:
    print("A KeyError occurred!")
else:
    print("No error occurred!")
finally:
    print("The finally statement ran!")

如果运行此示例,它将执行 elsefinally 声明。大多数时候,你不会看到 else 语句用作以下任何代码 try/except 如果没有引发错误,将执行。唯一的好用法是 else 我看到的语句是您要在其中执行的 第二 一段代码可以 also 引发错误。当然,如果在 else 那它就不会被抓住了。

总结

现在,您应该能够处理代码中的异常。如果您发现您的代码引发了异常,那么您将知道如何以这样一种方式包装它:您可以捕获错误并优雅地退出,或者不中断地继续。

现在我们已经准备好继续学习如何使用Python中的文件。