首页 > 开发 > Python > 正文

Python中的异常处理

2023-04-25 12:32:06
字体:
来源:转载
供稿:网友

一个程序即使语法正确,也可能在执行过程中会产生错误,这些错误往往会导致程序非预期提前终止。

在程序执行中遇到的错误,我们称之为异常(Exception)。

在程序中对异常进行处理可以提高用户的体验。

在Python中也提供了类似Java、C#等异常处理方法。

一、Python异常处理简介

Python使用try, except 和 finally三个关键字来处理异常,在异常处理形式上与其它语言相同,但语法使用的关键字稍有不同。

把可能出现异常的语句放在try语句块中,而异常的捕获与处理过程放在 except 语句块中。

在一次异常处理中可以包含多个except语句块,以便用于捕获和处理不同的异常。

不管异常是否发生,放在finally语句块中的语句总会被执行到。利用这个机制可以在程序中用于释放资源或在程序中出现异常时进行其他的处理操作,如保存游戏进度等。

在Python中也可以使用else语句块配合异常处理。即没有异常发生时执行else语句块中的语句。

二、Python中异常处理的方法

其语法格式如下:

try:
    #可能出现异常的语句
except 异常类1 as 变量1:
    #异常处理语句
except 异常类2 as 变量2:
    #异常处理语句
...
finally:
    #finally语句块

上面语法格式中,except可以出现多次,finally语句块是可选的语句块。

下面举例子来说明:

def divide(x, y):
    try:
        print(f"{x} / {y} = {x / y}")
    except ZeroDivisionError as e:
        print("发生错误:除数为0。")

divide(2008, 4)
divide(2008, 0)
divide(2008, 100)

输出情况如下:

2008 / 4 = 502.0
发生错误:除数为0。
2008 / 100 = 20.08

下面是没有异常处理的情况:

def divide(x, y):
    print(f"{x} / {y} = {x / y}")

divide(2008, 4)
divide(2008, 0)
divide(2008,100)

 输出情况如下:

2008 / 4 = 502.0
Traceback (most recent call last):
   File "D:/01Lesson/PY/exceptionhandle02.py", line 5, in <module>
      divide(2008, 0)
   File "D:/01Lesson/PY/exceptionhandle02.py", line 2, in divide
      print(f"{x} / {y} = {x / y}")
ZeroDivisionError: division by zero
从上面两个例子可以看出,在可能出现异常的地方若不对异常进行处理,将导致程序非预期终止(第3个函数调用并没有被执行),而使用异常处理后,在给出友好提示的同时,还能使程序继续执行下去。

在第1个例子中,我们使用了除数为0的异常类,并声明了变量e。但在程序中并没有使用它,实际上也可以省略它,省略时的样子如下:

def divide(x, y):
    try:
        print(f"{x} / {y} = {x / y}")
    except ZeroDivisionError:
        print("发生错误:除数为0。")

divide(2008, 4)
divide(2008, 0)
divide(2008, 100)

输出情况如下:

2008 / 4 = 502.0
发生错误:除数为0。
2008 / 100 = 20.08

 也可以在输出时直接输出变量e。例子如下:

def divide(x, y):
    try:
        print(f"{x} / {y} = {x / y}")
    except ZeroDivisionError as e:
        print(e)

divide(2008, 4)
divide(2008, 0)
divide(2008, 100)

输出情况如下:

2008 / 4 = 502.0
division by zero
2008 / 100 = 20.08

 二、异常基类

(1)BaseException 是所有内建异常的基类,不能被用户由用户定义的异常所继承;由该基类直接派生的子类有:

①Exception 见(2)中的描述;

②GeneratorExit 当生成器或协同进程被关闭时引发的异常;

③KeyboardInterrupt 当用户按下中断键(通常是control-c 或delete)时引发的异常;

④SystemExit 由sys.exit()函数引发的异常。

(2)Exception 所有内建,非系统退出性异常都派生于此类,用户定义的异常也由此类所派生;

(3)ArithmeticError  由算术错误导致的内建异常的基类: OverflowError, ZeroDivisionError, FloatingPointError.;

(4)BufferError  与缓冲区相关的操作无法执行时引发的异常;

(5)LookupError  当匹配或序列索引操作所提供的索引或键无效时引发的异常基类:IndexError, KeyError。

三、一些具体的内建异常类

(1)AssertionError 当assert语句无效时引发的异常;

(2)AttributeError 当引用属性或为其负值失败时引发的异常;

(3)EOFError 当调用input()函数没有读取到数据而到达文件末尾(EOF)时而引发的异常;

(4)ImportError 当import语句加载模块遇到问题时引发的异常;

(5)IndexError 序列操作下标超出范围时引发的异常;

(6)KeyError 在匹配的键在键集中未找到时引发的异常;

(7)MemoryError 当操作耗尽内存时引发的异常;

(8)NameError 在局部或全局中未找到相关命名时引发的异常;

(9)TypeError  当运算或函数调用使用的对象不匹配时引发的异常;

(10)ZeroDivisionError 在除法或取模运算中,第二个参数为0时引发的异常。

四、具有多个except语句块的异常处理

在实际中,一段代码可能会产生多种异常,我们可以使用多个except语句块来捕捉相应的异常进行处理。下面这个例子说明具有多个except语句块时的使用方法。

v1 = input("请输入被除数:")
v2 = input("请输入除数:")

try:
    x = float(v1)
    y = float(v2)
    q = x / y
    print(f"{x}÷{y} = {q}")
except TypeError as te:
    print(te)
except ZeroDivisionError as zde:
    print(zde)
except ValueError as ve:
   print(ve)

执行输入与输出情况:

请输入被除数:100
请输入除数:e
could not convert string to float: 'e'

请输入被除数:100
请输入除数:0
float division by zero

请输入被除数:100
请输入除数:5
100.0÷5.0 = 20.0

在Python 3.8.2 IDLE的执行情况如下图所示:

Python中捕获多个异常

五、捕获未知异常

在我们无法知道所有的异常类的情况下,我们可以使用except捕获所有可能的异常。即在except块中不必给出具体的异常类。下面一段程序演示了该种情况下的使用方法:

def divide(x, y):
    try:
        print(f"{x} / {y} = {x / y}")
    except ZeroDivisionError as e:
        print("发生错误:除数为0。")
    except:
        print("发生未知错误。")

divide(2008, 4)
divide(2008, 'a')
divide(2008, 0)
divide(2008, 100)

 执行输出结果如下:

2008 / 4 = 502.0
发生未知错误。
division by zero
2008 / 100 = 20.08
在我们无法知道程序具体发生哪些异常时,使用except捕获未知异常是一件非常有益的事情。

六、else语句块的使用

else语句块是可选部分。当try语句块没有捕获到异常时,就会执行else语句块中的内容。

下面程序中使用了else语句块:

def divide(x, y):
    try:
        print(f"{x}/{y}={x/y}")
    except ZeroDivisionError as e:
        print(e)
    else:
        print("函数一切正常。")

divide(2021, 3)
divide(2021, 0)
divide(2021, 10)

在Python 3.8.2 IDLE运行情况如下图所示:

Python异常处理else语句块的使用

从上面的例子中可以看出,当程序执行过程中没有遇到异常时就会输出else语句块中的内容:函数一切正常。

七、finally语句块的使用

不管程序是否遇到了异常,finally语句块都会被执行。这常常用于程序释放资源,执行一些清理性工作。下面的例子演示了finally语句块的使用。

def divide(x, y):
    try:
        print(f"{x}/{y}={x/y}")
    except ZeroDivisionError as e:
        print(e)
    finally:
        print("finally:清理活动。")

divide(2021, 3)
divide(2021, 0)
divide(2021, 10)

运行结果如下:

2021/3=673.6666666666666
finally:清理活动。
division by zero
finally:清理活动。
2021/10=202.1
finally:清理活动。

在Python 3.8.2 IDLE的运行情况如下图所示:

Python异常处理finally语句块的使用

以上是关于Python中异常处理的基本情况,在今后的文章中将进一步讲解用户自定义异常的方法。

本文(完)

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表