• Python中的异常(Exceptions)介绍
  • 发布于 2个月前
  • 188 热度
    0 评论
Python程序一旦遇到错误就会终止。 在Python中,错误可能是语法错误或异常。 在本文中,您将看到什么是异常以及它与语法错误的区别。 之后,您将了解如何抛出异常和做出断言。 然后,您将看到try和except块的演示。

异常与语法错误

解析器检测到错误的语句时会发生语法错误。 观察下面的例子:

>>> print( 0 / 0 ))
  File "<stdin>", line 1
    print( 0 / 0 ))
                  ^
SyntaxError: invalid syntax

箭头指出解析器遇到语法错误的位置。 在这个例子中,多了一个右括号。 删除它并再次运行你的代码:

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

这一次,你遇到了一个异常错误。 无论何时语法正确的Python代码导致错误,这种类型的错误就会发生。 消息的最后一行指出了遇到的异常错误类型。

Python不会显示exception error消息,而是详细说明遇到了什么类型的异常错误。 在这种情况下,它是一个ZeroDivisionError。 Python带有各种内置的异常,同样也可以创建自定义异常。


抛出异常
如果某种条件发生,我们可以使用raise来抛出异常。 该声明可以实现一个自定义异常。

如果你想在某种情况发生时使用raise来抛出错误,你可以这样做:

x = 10
if x > 5:
    raise Exception('x should not exceed 5. The value of x was: {}'.format(x))

当你运行这段代码时,输出如下:
Traceback (most recent call last):
  File "<input>", line 2, in <module>
AssertionError: This code runs on Linux only.

该程序停下来,并将异常显示到屏幕,提供有关错误的线索。


AssertionError异常
与其等待程序中途崩溃,您还可以先在Python中进行断言。 我们断言某个条件得到满足。 如果这种情况证明是True,那很好! 该程序可以继续。 如果断言结果为False,你可以让程序抛出一个AssertionError异常。

看看下面的例子,它断言代码将在Linux系统上执行:
import sys
assert ('linux' in sys.platform), "This code runs on Linux only."
如果您在Linux机器上运行此代码,则断言会通过。 如果您要在Windows计算机上运行此代码,则断言的结果将为False,输出如下所示:
Traceback (most recent call last):
  File "<input>", line 2, in <module>
AssertionError: This code runs on Linux only.
在这个例子中,抛出一个AssertionError异常是该程序最后一件事。 程序将停止并不再继续。 如果这不是你想要的呢?


try和except块:处理异常

Python中的try和except块用于捕获和处理异常。 Python将try语句之后的代码作为程序的“正常”部分执行。 except语句后面的代码是程序对前面的try子句中的任何异常的响应。

正如您前面所看到的,当语法正确的代码遇到错误时,Python将抛出异常错误。 如果该程序未处理它,该异常错误会使程序崩溃。 except子句决定程序如何响应异常。
以下函数可以帮助您了解try和except块:
def linux_interaction():
    assert ('linux' in sys.platform), "Function can only run on Linux systems."
    print('Doing something.')

linux_interaction()只能在Linux系统上运行。 如果在除Linux以外的操作系统上调用该函数,则此函数中的断言将引发AssertionError异常。
你可以使用下面的代码试试这个函数:
try:
    linux_interaction()
except:
    pass
这里处理错误的方式是直接使用pass。 如果您要在Windows机器上运行此代码,您将得到以下输出:

没有任何输出。 这里的好处是该程序没有崩溃。 但是,如果您运行代码时发现某种类型的异常,可能会好些。 为此,您可以将pass更改为可生成消息的内容,如下所示:
try:
    linux_interaction()
except:
    print('Linux function was not executed')
在windows上执行这段代码:
Linux function was not executed
当运行此函数的程序中发生异常时,程序将通知您函数调用不成功的事实同时继续运行。
你没有看到的是由于函数调用而抛出的错误类型。 为了准确地查看出了什么问题,您需要捕捉函数抛出的错误。
以下代码是捕获AssertionError并将该消息输出到屏幕的示例:
try:
    linux_interaction()
except AssertionError as error:
    print(error)
    print('The linux_interaction() function was not executed')
在Windows上运行此功能会输出以下内容:
Function can only run on Linux systems.
The linux_interaction() function was not executed
第一条消息是AssertionError,通知您该函数只能在Linux上执行。 第二条消息告诉你哪个功能没有执行。
在前面的例子中,你调用了自己写的一个函数。 当执行该函数时,捕获了AssertionError异常并将其打印到屏幕上。
以下是另一个打开文件并使用内置异常的示例:
try:
    with open('file.log') as file:
        read_data = file.read()
except:
    print('Could not open file.log')
如果file.log不存在,这段代码将输出以下内容:
Could not open file.log
这是一条信息丰富的消息,我们的程序仍将继续运行。 在Python文档中,可以看到有很多可用的内置异常。 该页面上描述的一个异常如下:
Exception FileNotFoundError
Raised when a file or directory is requested but doesn’t exist. Corresponds to errno ENOENT.

要捕获这种类型的异常并将其打印到屏幕上,可以使用以下代码:
try:
    with open('file.log') as file:
        read_data = file.read()
except FileNotFoundError as fnf_error:
    print(fnf_error)
在这种情况下,如果file.log不存在,则输出如下所示:
[Errno 2] No such file or directory: 'file.log'
您可以在try子句中使用多个函数调用,并预计捕获各种异常。 这里需要注意的是,try子句中的代码只要遇到异常就会停止。
警告:捕捉异常会隐藏所有错误...即使是那些完全意外的错误。 这就是为什么你应该避免在你的Python程序中使用空except子句。 相反,你会想要引用你想要捕获和处理的特定异常类。 您可以在本教程中了解更多关于这样做的好处。
看下面的代码。 在这里,你首先调用linux_interaction()函数,然后尝试打开一个文件:
try:
    linux_interaction()
    with open('file.log') as file:
        read_data = file.read()
except FileNotFoundError as fnf_error:
    print(fnf_error)
except AssertionError as error:
    print(error)
    print('Linux linux_interaction() function was not executed')

如果文件不存在,在Windows上运行此代码将输出以下内容:
Function can only run on Linux systems.
Linux linux_interaction() function was not executed
在try子句中,您立即遇到了异常,并没有进入您尝试打开file.log的部分。 现在看看在Linux上运行代码时会发生什么:
[Errno 2] No such file or directory: 'file.log'
关键要点如下:
1.执行try子句直到遇到第一个异常。
2.在except子句或异常处理程序中,您可以确定程序如何响应异常。
3.您可以预见多个异常,并区分程序应该如何响应它们。
4.避免使用空except子句。

else子句
在Python中,使用else子句,只有在没有异常的情况下,才能指示程序执行某个代码块。

看一下下面的例子:
try:
    linux_interaction()
except AssertionError as error:
    print(error)
else:
    print('Executing the else clause.')
如果您要在Linux系统上运行此代码,则输出结果如下所示:
Doing something.
Executing the else clause.
由于该程序没有遇到任何异常,因此执行了else子句。
您还可以尝试在else子句中运行代码,并捕获可能的异常:
try:
    linux_interaction()
except AssertionError as error:
    print(error)
else:
    try:
        with open('file.log') as file:
            read_data = file.read()
    except FileNotFoundError as fnf_error:
        print(fnf_error)
如果您要在Linux上执行此代码,您将得到以下结果:
Doing something.
[Errno 2] No such file or directory: 'file.log'

从输出中,您可以看到linux_interaction()函数运行。 由于没有遇到任何异常,因此尝试打开file.log。 由于该文件不存在而无法打开,引发了FileNotFoundError异常


使用finally语句做最后后清理
想象一下,执行代码后,你总是必须执行某种操作来清理。 Python可以使用finally子句进行操作。

来看看下面的例子:

try:
    linux_interaction()
except AssertionError as error:
    print(error)
else:
    try:
        with open('file.log') as file:
            read_data = file.read()
    except FileNotFoundError as fnf_error:
        print(fnf_error)
finally:
    print('Cleaning up, irrespective of any exceptions.')

在前面的代码中,finally子句中的所有内容都将被执行。 即使在try或else子句中遇到异常,也不会影响finally子句的执行。 在Windows上运行以前的代码将输出以下内容:
Function can only run on Linux systems.
Cleaning up, irrespective of any exceptions.
汇总
在看到语法错误和异常之间的区别之后,您了解了在Python中抛出,捕获和处理异常的各种方法。 在本文中,您看到了以下选项:
1.raise允许你随时抛出异常。
2.assert使您能够验证是否符合某个条件,如果不符合则抛出异常。
3.在try子句中,遇到异常之前的所有语句都会执行。
4.except用于捕获和处理try子句中遇到的异常。
5.else使你可以编写只有在try子句中没有遇到任何异常时才能运行的代码。
6.finally使您能够执行应始终运行的代码段,无论是否遇到任何异常。

用户评论