1、异常概念
程序运行时,如果Python解释器遇到一个错误,会停止程序的执行并且提示一些错误信息,这就是异常
2、捕获异常
① 简单的异常处理
语法格式
try:
可能发生错误的代码
except:
如果出现异常执行的代码
示例:
需求:要求用户输入整数
try:
num = int(input("请输入一个整数"))
print("输入整数有效!")
except:
print("请输入正确的整数!")
当用户输入整数时,能被int转换时会执行try中的代码块
请输入一个整数:10
输入整数有效!
当用户输入不是整数时,不能被int转换时会执行except中的代码块
请输入一个整数:abc
请输入正确的整数!
通过结果说明:使用try来尝试执行后面语句块中的代码,如果代码发生异常问题,那么异常信息就会被except捕捉到,可以在except后面进行异常处理,如果代码没有异常,那么程序就正常运行,不会执行except后的代码。
② 捕捉指定异常类型
在程序执行时,可能会遇到不同类型的异常,并且需要针对不同类型的异常做出不同的响应,这个时候就需要捕获错误类型了。
当Python解释器抛出异常时,最后一行错误信息的第一个单词就是错误类型。
语法格式
第一种:捕捉指定单个错误类型
try:
尝试执行的代码
except 错误类型1:
针对错误类型1,做出相应的代码处理
第二种:捕捉指定多个错误类型(将多个异常通过圆括号包裹成一个元组)
try:
尝试执行的代码
except (错误类型1,错误类型2,错误类型3……):
针对错误类型1、2、3……,做出相应的代码处理
第三种:异常别名--获取异常信息
try:
尝试执行的代码
except (错误类型1,错误类型2,错误类型3……)as e:
print(e)
当异常发生时,处理异常的代码
示例:
需求:提示用户输入一个整数,使用8除以用户输入的整数并输出
num = int(input("请输入一个整数"))
result = 8 / num
print(result)
输入的值不同,错误提示不同:
1)当输入字母时提示:值错误的异常
2)当输入数字0时,因为分母不能为0,提示:除0错误异常
针对两种不同的错误类型分别给用户不同的提示代码:
try:
num = int(input("请输入一个整数:"))
result = 8 / num
print(result)
except ValueError:
print("请输入正确的整数")
except ZeroDivisionError:
print("除0错误")
当用户输入字母时,执行的结果
请输入一个整数:abc
请输入正确的整数
当用户输入0时,执行的结果
请输入一个整数:0
除0错误
③ 捕获所有异常
如果异常的种类不确定,则可以使用exception来指代所有种类的异常。
语法格式
try:
pass
except Exception as e:
print(e)
示例
try:
num = int(input("请输入一个整数:"))
result = 8 / num
print(result)
except ValueError:
print("请输入正确的整数")
except Exception as e:
print("未知错误 %s"%e)
当输入0时
请输入一个整数:0
未知错误division by zero
3.异常的传递性
- 当代码出现了多层级的调用时,在其中发生了异常,如果没有处理这个异常,这个异常会自动向上抛出
- 如果上层也没有处理,那么再继续向上抛出,直到抛到解释器,解释器默认处理异常的方式就是中断程序,将异常信息显示控制台上
示例
# 异常的传递
def func_a():
print('Func a run ...')
func_b()
def func_b():
print("Func b run ...")
func_c()
def func_c():
print('Func c run ...')
print(1 / 0)
func_a()
运行
解决方法
① 可以在抛异常的代码中处理异常
def func_a():
print('Func a run ...')
func_b()
def func_b():
print("Func b run ...")
func_c()
def func_c():
print('Func c run ...')
try:
print(1 / 0)
except Exception:
print("除数不能为零!")
func_a()
运行结果
② 因为异常具有传递性,可以在调用的代码中处理异常
def func_a():
print('Func a run ...')
func_b()
def func_b():
print("Func b run ...")
try:
func_c()
except Exception:
print("除数不能为零!")
def func_c():
print('Func c run ...')
print(1 / 0)
func_a()
运行结果
4.异常捕获中else和finally语句
- else表示的是没有异常要执行的代码
- finally表示无论是否发生异常都要执行的代码
示例
try:
f = None #如果不加这段代码会报变量不存在异常
f = open('b.txt','r')
except Exception as e:
print('要打开的文件不存在')
print(e)
else:
# 对文件的读取操作
print('else 是当没有出现异常时,执行的else语句 块')
print(f.read())
finally:
# 不管是否出现异常,都要执行这个语句块
# 一般这个模块中,主要写的内容 是资料关闭或回收
# 比如,文件的关闭,网络连接的关闭,数据库的关闭
print('无论是否出现异常,都会执行finally语句 块')
if f != None:
f.close()
运行结果(b.txt文件不存在)
5.语法糖
用with替代try-except
with open('a.txt','r') as f:
f.read()
6.自定义异常和抛出异常
所有异常都直接或间接继承Exception这个父类
语法格式
第一种:
class 异常名Error(Exception):
pass
第二种:
class 异常名Error(Exception):
def __init__(self,msg):
self.__msg = msg
def __str__(self):
return self.__msg
示例
新建自定义模块a.py (自定义异常是从开发者角度)
# 定义一个用来判断当前手机号是否有非法字符的异常
class PhoneNumberNotDigitError(Exception):
pass
# 定义一个用来判断手机号位数是否合法的异常
class PhoneNumberLengthError(Exception):
def __init__(self,msg):
self.__msg = msg
def __str__(self):
return self.__msg
# 定义一个函数,用来获取一个电话号码
def get_phone_number():
pn = input("请输入一个11位的手机号:")
if pn.isdigit() == False:
# 抛出自定义的异常
raise PhoneNumberNotDigitError()
elif len(pn) != 11:
raise PhoneNumberLengthError("手机号位数不正确")
return "输入的手机号是合法的:"+pn
导入a.py模块
from a import *
get_phone_number()
运行结果
1)当输入手机号位数不正确时,抛出自定义PhoneNumberLengthError异常
2)当输入手机号不是纯数字时,抛出自定义PhoneNumberNotDigitError异常
解决自定义异常
from a import *
try:
num = get_phone_number()
# 或者直接写except Exception as e
except(PhoneNumberNotDigitError,PhoneNumberLengthError) as e:
print(e)
else:
print(num)
运行结果 1)当输入号码正确时
2)当输入的号码不正确时
3)当输入的号码不是11位时