异常概述
异常就是程序运行的错误,以下是Python中常见的异常类型
异常 | 说明 |
---|---|
NameError | 尝试访问一个没有声明的变量引发的错误 |
IndexError | 索引超出序列范围引发的错误 |
IndentationError | 缩进错误 |
ValueError | 传的入值错误 |
KeyError | 请求一个不存在的字典关键字引发的错误 |
IOError | 输入输出错误(如要读取的文件不存在) |
ImprotError | 当 import 语句无法找到模块 或 from 无法在模块中找到相应的名称时引发的错误 |
TypeError | 类型不合适引发的错误 |
MemoryError | 内存不足错误 |
ZeroDivisionError | 除数为 0 引发的错误 |
在此处模拟一个错误,用于下文说明。
一个幼儿园老师给小盆友分苹果,输入苹果数量和小朋友数量,返回平均每个小朋友分得几个,还剩几个。
def division():
'''功能:分苹果'''
print('\n','='*15,' 分苹果了 ','='*15,'\n')
apple = int(input('请输入苹果的数量:')) # 输入苹果数
children = int(input('请输入来了多少小朋友:')) # 输入小朋友数
result = apple//children # 计算没人分几个
remain = apple - result*children # 计算剩下几个
if remain>0:
print(apple,'个苹果,平均分给',children,'个小朋友,每人分',result,'个,剩下',remain,'个。')
print('%d个苹果,平均分给%d个小朋友,每人分%d个,剩下%d个。'%(apple,children,result,remain))
else:
print(apple,'个苹果,平均分给',children,'个小朋友,每人分',result,'个。')
print('%d个苹果,平均分给%d个小朋友,每人分%d个。'%(apple,children,result))
if __name__ == '__main__': # 调用分苹果函数
division() # 调用函数
在以上代码中,当输入的小朋友数量为 0 时,除数为零,将会报错。后文将以此为例,讲解如何处理异常。
异常处理语句
主要有以下四种语句:
- try ··· except
- try ··· except ··· finally
- try ··· except ··· else
- 使用 raise 语句抛出异常
try ··· except
可以捕获异常,并给出相应的处理结果。基本语法如下:
try:
block1 # 可能出现异常的代码,当代码出现错误时,会跳转到 bolck2
except [ExceptionName [as alias]]: # 可选参数,用来指定要捕获的异常,
bolck2 # 处理结果放在此处,如果 block1 异常,则不会执行
参数 | 说明 |
---|---|
block1 | 可能出现异常的代码。当代码出现异常时,跳转到 bolck1。 |
bolck2 | 异常处理方案。如果 block1 没有异常,则不会执行。 |
ExceptinoName | 可选参数,用于指定要捕获的异常。 当指定时,只有出现指定的错误才会执行 bolck2;否则,出现任意错误均执行 bolck2。 注:当要捕获多个异常时,可以写多个 except 语句,或者将多个 ExceptionName 放入列表中。 |
as alias | 可选参数,指定异常的别名。 便于在输出异常内容时,可以通过别名表示,从而简化代码。 |
以下为处理实例:
def division():
'''功能:分苹果'''
print('\n','='*15,' 分苹果了 ','='*15,'\n')
apple = int(input('请输入苹果的数量:')) # 输入苹果数
children = int(input('请输入来了多少小朋友:')) # 输入小朋友数
result = apple//children # 计算没人分几个
remain = apple - result*children # 计算剩下几个
if remain>0:
print(apple,'个苹果,平均分给',children,'个小朋友,每人分',result,'个,剩下',remain,'个。')
print('%d个苹果,平均分给%d个小朋友,每人分%d个,剩下%d个。'%(apple,children,result,remain))
else:
print(apple,'个苹果,平均分给',children,'个小朋友,每人分',result,'个。')
print('%d个苹果,平均分给%d个小朋友,每人分%d个。'%(apple,children,result))
if __name__ == '__main__': # 调用分苹果函数
try:
division() # 调用函数
except ZeroDivisionError: # 捕获输入除数为 0 的错误
print('\n出错了——苹果不能被零个小朋友分。')
except ValueError as ve: # 捕获输入小数的错误,并将错误名称命名为 ve
print('\n输入错误:', ve)
# 以上两个异常捕获语句也可以合并为以下一个语句
except (ZeroDivisionError, ValueError) as e:
print('\n', e)
try ··· except ··· else
在捕获异常时,想要对没有出现异常的情况进行处理,使用此方法。语法如下:
try:
block1 # 可能出现异常的代码,当代码出现错误时,会跳转到 bolck2
except [ExceptionName [as alias]]: # 可选参数,用来指定要捕获的异常,
block2 # 处理结果放在此处,如果 block1 异常,则不会执行
else:
block3
该语法前半部分与 try ··· except ···
一致。block3
部分时是在 block1
没有异常时执行的。
以下为实例:
def division():
'''功能:分苹果'''
print('\n','='*15,' 分苹果了 ','='*15,'\n')
apple = int(input('请输入苹果的数量:')) # 输入苹果数
children = int(input('请输入来了多少小朋友:')) # 输入小朋友数
result = apple//children # 计算没人分几个
remain = apple - result*children # 计算剩下几个
if remain>0:
print(apple,'个苹果,平均分给',children,'个小朋友,每人分',result,'个,剩下',remain,'个。')
print('%d个苹果,平均分给%d个小朋友,每人分%d个,剩下%d个。'%(apple,children,result,remain))
else:
print(apple,'个苹果,平均分给',children,'个小朋友,每人分',result,'个。')
print('%d个苹果,平均分给%d个小朋友,每人分%d个。'%(apple,children,result))
if __name__ == '__main__': # 调用分苹果函数
try:
division() # 调用函数
except (ZeroDivisionError, ValueError) as e: # 捕获两个异常
print('\n', e)
else:
print('分苹果顺利完成!')
try ··· except ··· finally
想要在捕获异常时,无论是否出现异常,有都要执行的语句,就可将其放在 finally
之后。语法如下:
try:
block1 # 可能出现异常的代码,当代码出现错误时,会跳转到 bolck2
except [ExceptionName [as alias]]: # 可选参数,用来指定要捕获的异常,
block2 # 处理结果放在此处,如果 block1 异常,则不会执行
finally:
block3
注意,finally
和 else
语句可以共用。实例运用如下:
def division():
'''功能:分苹果'''
print('\n','='*15,' 分苹果了 ','='*15,'\n')
apple = int(input('请输入苹果的数量:')) # 输入苹果数
children = int(input('请输入来了多少小朋友:')) # 输入小朋友数
result = apple//children # 计算没人分几个
remain = apple - result*children # 计算剩下几个
if remain>0:
print(apple,'个苹果,平均分给',children,'个小朋友,每人分',result,'个,剩下',remain,'个。')
print('%d个苹果,平均分给%d个小朋友,每人分%d个,剩下%d个。'%(apple,children,result,remain))
else:
print(apple,'个苹果,平均分给',children,'个小朋友,每人分',result,'个。')
print('%d个苹果,平均分给%d个小朋友,每人分%d个。'%(apple,children,result))
if __name__ == '__main__': # 调用分苹果函数
try:
division()
except (ZeroDivisionError, ValueError) as e:
print('\n', e)
else:
print('分苹果顺利完成!')
finally:
print('进行了一次分苹果的操作。')
关于异常的流程可以简单总结如下:
使用 raise 语句抛出异常
当某个函数或方法可能会产生异常,但是我们不想在当前的函数或方法运行时处理这个异常,就可以使用 raise
语句在函数或方法中抛出异常。语法如下:
raise [ExceptionName [(reason)]]
- 如果省略参数(只保留
raise
),则会把当前的错误原样抛出 (reason)
参数指定了 “异常说明”- 如果只定义了
ExceptionName
参数(即raise ExceptionName
),即指定了一个异常,那么在抛出异常时不会附带有任何异常信息。 - 当执行了 raise 语句后,之后的语句即不再执行
案例演示仍采取分苹果,但是增加了限制条件:苹果个数必需要大于小朋友的个数,从而保证每个小朋友至少分到一个苹果。具体如下:
def division():
'''功能:分苹果'''
print('\n','='*15,' 分苹果了 ','='*15,'\n')
apple = int(input('请输入苹果的数量:')) # 输入苹果数
children = int(input('请输入来了多少小朋友:')) # 输入小朋友数
###############################################################################################
if apple < children: #增加判断语句,判断苹果数是否大于小朋友数量
raise ValueError('苹果太少了,不够分!') # 抛出异常语句
# 当执行了 raise 语句后,之后的语句即不再执行
###############################################################################################
result = apple//children # 计算没人分几个
remain = apple - result*children # 计算剩下几个
if remain>0:
print(apple,'个苹果,平均分给',children,'个小朋友,每人分',result,'个,剩下',remain,'个。')
print('%d个苹果,平均分给%d个小朋友,每人分%d个,剩下%d个。'%(apple,children,result,remain))
else:
print(apple,'个苹果,平均分给',children,'个小朋友,每人分',result,'个。')
print('%d个苹果,平均分给%d个小朋友,每人分%d个。'%(apple,children,result))
if __name__ == '__main__': # 调用分苹果函数
try:
division()
except (ZeroDivisionError, ValueError) as e:
print('\n', e)
以上代码执行了 “捕获异常” 的操作,当不执行捕获异常时,rasie
语句定义的异常内容将直接作为运行异常抛出。