1.10- 异常处理 try except

在python中,程序运行时出现错误后程序会终止,这种错误不是程序设计的错误,它是在程序运行时的运行错误,称为运行时错误(Runime Error),处理这种错误要用到try/except异常处理语句。
例如:

import math n=input("请输入:") try: n=float(n) print(math.sqrt(n)) print("done") except Exception as err: print("Err:",err) print("end")

运行结果如下:

请输入:12a Err: could not convert string to float: '12a' end 请输入:-5 Err: math domain error end

python中有很多异常类。对于不同的异常情况有不同的异常类对象,设计不同的异常类对象处理不同的异常是为了在异常类中更好地反映异常的信息。Exception异常类是使用最多的一个。

1、异常语句 try…except…
python的try语句是异常处理语句,try语句格式如下:

try: 语句块1 except Exception as err: 语句块2 后续语句

它的执行规则是:
<1> 先执行语句块1,如语句块1的各条语句都能正确执行,不出现任何运行错误,则在执行完语句块1的最后一条语句后,try语句执行完毕,转后面的程序后续语句。
<2> 若在执行语句块1的过程中出现运行错误,则停止语句块1的执行,这个错误被系统铺捉到,而且错误的信息被转为Excepion异常类对象,转去执行语句块2,当语句块2执行完后,try语句执行完毕,转后面的程序后续语句。
<3> 语句块1是try执行的程序段,语句块2是语句块1发送运行错误并且被捕捉(except)到后执行的程序段。

执行流程图如下:

在try语句中,Exception是python的一个类,err是捕捉到的错误对象,专门表示错误异常。Exception是系统对象名称,不可改变。err是我们给出的变量名,可以更改。

例如:

print("begin") # 除数不能为0演示异常的执行过程 try: print("divided") n=1/0 print("finish") except Exception as err: print("err:",err) print("end")

执行结果如下:

begin divided err: division by zero end

2、抛出异常 raise
异常是程序运行时的一种错误,那么这个异常时如何抛出的呢?
在python中抛出异常的语句是raise语句,格式如下:

raise Exception(异常信息)

其中raise是抛出语句,Exception(异常信息)表示建立一个异常类Exception的对象,该对象用指定的字符串设置其Message属性。
例如:

# 用raise 语句抛出异常 print("begin") try: print("try begin") raise Exception("my test err") print("finish") except Exception as err: print("err:",err) print("end")

执行结果如下:

begin try begin err: my test err end

3、简单异常处理语句
有时我们不太关心异常的信息,只需要捕捉到异常即可,这时在except中不用写Exception部分,try语句简化为:

try: 语句块1 except: 语句块2 后续语句

例如:

# 应用异常处理,输入一个整数,计算平方根 import math while True: try: n=input("请输入:") n=int(n) if n<0: raise Exception() break except: print("请输入正整数") print(math.sqrt(n)) print("done")

执行结果如下:

请输入:-5 请输入正整数 请输入:10 3.1622776601683795 done

案例:输入学生姓名Name、性别Gender、年龄Age,要求 姓名Name非空、性别Gender为“男”或“女”, 年龄Age在18-30之间。
案例分析:构造一个异常语句结构,输入学生的姓名Name、性别Gender、年龄Age,如果有错误就抛出异常。
程序如下:

try: name=input("请输入学生姓名:") if name.strip()=="": raise Exception("无效的姓名") gender=input("请输入学生性别:") if gender!="男" and gender!="女": raise Exception("无效的性别") age=input("请输入学生年龄:") age=float(age) if age<18 or age>30: raise Exception("无效的年龄") print("输入学生的姓名为:",name," 性别为:",gender," 年龄为:",age) except Exception as err: print(err) 运行结果如下: 请输入学生姓名:大富 请输入学生性别:1 无效的性别 请输入学生姓名:大富 请输入学生性别:女 请输入学生年龄:60 无效的年龄

程序中这里可能发生异常那里也可能发生异常,那么是不是有可能发生异常的地方都使用try异常处理语句进行异常扑捉呢?如果这样的化程序太复杂,实际上异常有传递机制,就是一个地方发生的异常如果没有被扑捉处理的话,它可以一层层传递,一直到被扑捉为止。

在python中如果一个函数抛出一个异常,那么在调用函数的地方可以捕捉到这个异常。

# 函数的异常捕捉,函数抛出异常,被调用函数的地方捕捉到 def fun(): print("begin") n=1/0 print("end") try: fun() except Exception as err: print(err)

程序执行结果:

begin division by zero

由此可见fun 函数中出现的异常在主程序调用 fun 时可以捕捉到, Python 程序一个地方出现异常,那么异常会传递到上一级调用的地方,这个过程会一直传递下去,直到异常被扑捉到为止,如果整个过程都没有遇到扑捉语句,程序就会因异常而结束。因此如果在 fun 中已经捕捉了异常,那么调用的主程序位置就捕捉不到了。

# 函数捕捉到异常,则调用函数的主程序就捕捉不到了 def fun(): print("begin") try: n=1/0 print("end") except Exception as err: print("fun err:",err) try: fun() except Exception as err: print("main err",err)

程序执行结果:

begin fun err: division by zero

异常传递示例:

# 异常的传递 def a(): print("begin a") n=1/0 print("end a") def b(): print("begin b") a() # 函数b调用函数a print("end b") try: b() # 主程序调用函数b,异常发生在函数b调用的函数a中,异常发生了传递 print("main done") except Exception as err: print(err) print("finish")

程序执行结果如下:

begin b begin a division by zero finish

由此可见函数A 中出现的异常自己没有捕捉,在调用函数 B 中也没有捕捉,最后在主
程序中被捕捉到,即异常有传递性,在一个函数中没有被捕捉的异常会传递给调用这个函数的另外函数,这个过程会一直传递下去,直到异常被捕捉为止,就不再往后传递了。

# 异常的传递 def a(): print("begin a") n=1/0 print("end a") def b(): print("begin b") try: a() except Exception as err: # 异常在b函数中捕捉到,则主程序不会再捕捉到 print(err) print("end b") try: b() print("done") except Exception as err: print(err) print("main end")

程序执行结果:

begin b begin a division by zero end b done main end

如果出现的异常一直没有被捕获,那么就传递到系统,程序就会终止。

# 异常引起程序终止 def a(): print("begin a") n=1/0 print("end a") def b(): print("begin b") a() print("end b") b() print("main end")

程序执行结果:

begin b begin a ZeroDivisionError: division by zero

案例:时间的输入与显示
案例描述:输入一个有效的时间,并显示
案例说明:设置时间格式为hⓂ️s,输入保证hⓂ️s有效,否则抛出异常
案例程序:

def myTime(): h=input("请输入时间中的小时:") h=int(h) # 转换错误被main程序捕捉 # 小时必须介于0-23之间 if h<0 or h>23: raise Exception("无效的小时") m=input("请输入时间中的分钟:") m=int(m) # 转换错误被main程序捕捉 # 分钟必须介于0-59之间 if m<0 or m>59: raise Exception("无效的分钟") s=input("请输入时间中的秒:") s=int(s) # 转换错误被main程序捕捉 # 秒必须介于0-59之间 if s<0 or s>59: raise Exception("无效的秒") print("%02d:%02d:%02d"%(h,m,s)) try: myTime() except Exception as err: print(err)