八、异常处理
1. 异常的概念
异常是指程序运行的过程中出现了错误,也叫Bug。
案例一:
# 定义人类
class Person:
# 属性 姓名
name = None
# 属性 年龄
age = None
print(Person().sex)
执行结果:
案例二:
print(2 / 0)
执行结果:
0是不能作为被除数的,所以程序也出异常了。
2. 异常捕获与处理
如果出现程序异常,我们不去捕获和处理,那么程序遇到异常,就直接终止,后续的代码无法继续执行,这将是可怕的事情。 Python提供了完善的异常处理机制,可以实现捕获异常,处理异常,最终实现代码继续运行下去。从而 让程序具有极好的容错性,让程序更加的健壮。
使用try...except捕获异常
基本语法:
try:
可能会有异常的代码
except:
出现异常的执行代码
示例:
try:
print(2 / 0)
except:
print("出现了异常")
print("异常被捕获,程序继续执行")
执行结果:
出现了异常
异常被捕获,程序继续执行
经过上面的处理,程序不会中断。
捕获指定的异常
try:
print(2 / 0)
except ZeroDivisionError as z:
print("出现了异常")
print("程序继续")
执行结果:
出现了异常
程序继续
多个except:
class Person:
# 属性 姓名
name = None
# 属性 年龄
age = None
# 多个except
try:
print(Person().sex)
except ZeroDivisionError as e:
print("出现了除0异常")
except AttributeError as a:
print("出现属性异常")
print("程序继续")
执行结果:
出现属性异常
程序继续
捕获所有异常,BaseException异常类是所有异常类的基类(老祖宗类),所有异常类都是直接或者间接继承BaseException异常类,Exception类是继承BaseException,并且有很多具体实现,大部分的异常类直接继承Exception,所以我们一般开发用Exeption。
try:
print(2 / 0)
except Exception as e:
print("出现了异常")
print("程序继续")
多异常捕获
假如程序块可能出现异常的种类比较多,我们可以用多异常捕获,只要出现其中一个异常,就会捕获到。
语法:
try:
可能会有多种异常的代码
except (异常1,异常2...异常N):
出现异常的执行代码
示例:
try:
print(Person().sex)
except (ZeroDivisionError, AttributeError):
print("出现了除0异常或者属性异常")
except:
print("出现了未知异常")
print("程序继续")
执行结果:
出现了除0异常或者属性异常
程序继续
else块
在Python的异常处理流程中还可添加一个else块,当 try块没有出现异常时,程序会执行else块。例如如下程序:
try:
print(2 / 1)
except:
print("出现了异常")
else:
print("else块")
print("1")
print("程序继续")
执行结果:
2.0
else块
1
程序继续
finally块
在异常处理中,finally块中的代码无论是否出现异常,都会执行。 有些时候,程序在try块里打开了一些物理资源(例如数据库连接、网络连接和磁盘文件等),这些物理资源都必须被显式回收。
try:
print(2 / 0)
except:
print("出现了异常")
else:
print("没有出现异常,我们做一些操作")
finally:
print("无论是否有异常,都会执行")
print("程序继续")
执行结果:
出现了异常
无论是否有异常,都会执行
程序继续
3. 使用raise引发异常
当程序出现错误时,系统会自动引发异常。除此之外,Python也允许程序自行引发异常,自行引发异常使用raise
语句来完成。
一般是业务逻辑上,业务异常问题,我们可以自行引发异常。
语法格式: raise [exceptionName [(reason)]]
案例:
try:
age = 17
if age < 18:
raise Exception
else:
print("放行")
except Exception as e:
print(type(e))
执行结果:
<class 'Exception'>
4. 自定义异常类
实际开发中,有时候系统提供的异常类型不能满足开发的需求。这时候你可以通过创建一个新的异常类 来拥有自己的异常。异常类继承自 Exception
类,可以直接继承,或者间接继承。
示例:
class TooLongException(Exception):
def __init__(self, length):
self.lenght = length
def __str__(self):
return f"长度是{self.lenght},超长了"
def name_test():
try:
name = input("请输入您的姓名:")
if len(name) > 4:
raise TooLongException(len(name))
else:
print(name)
except TooLongException as tle:
print("出现异常,", tle)
name_test()
执行结果:
请输入您的姓名:家里好舒服
出现异常, 长度是5,超长了
5. 异常的传递性
异常是具有传递性的,假如方法A调用方法B,方法B调用方法C,如果方法C代码出现异常,并且没有处理异常,则会传递给方法B,同理,如果B依然没有处理异常,则最终传递给方法A。
示例:
def funC():
print("funC开始")
a = 1 / 0
print("funC结束")
def funB():
print("funB开始")
funC()
print("funB结束")
def funA():
print("funA开始")
funB()
print("funA结束")
try:
funA()
except Exception as e:
print(e)
执行结果:
funA开始
funB开始
funC开始
division by zero