第七章 - 异常处理¶
当程序中发生错误时,您会怎么做?假设您试图打开一个文件,但是您输入了错误的路径,或者您向用户询问信息,他们输入了一些垃圾。您不希望程序崩溃,因此实现异常处理。在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 我们访问一个存在的密钥。这是可行的,所以 KeyError 是 not 提高。因为没有错误, 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!")
如果运行此示例,它将执行 else 和 finally 声明。大多数时候,你不会看到 else 语句用作以下任何代码 try/except 如果没有引发错误,将执行。唯一的好用法是 else 我看到的语句是您要在其中执行的 第二 一段代码可以 also 引发错误。当然,如果在 else 那它就不会被抓住了。
总结¶
现在,您应该能够处理代码中的异常。如果您发现您的代码引发了异常,那么您将知道如何以这样一种方式包装它:您可以捕获错误并优雅地退出,或者不中断地继续。
现在我们已经准备好继续学习如何使用Python中的文件。