异常处理
异常处理
1、什么是异常
异常指的是程序运行发生错误的信号,程序在运行工程中一旦出错,就会抛出异常,程序也会随着结束掉。
print('start')
[1, 2, 3][100]
print('stop')
# start
# IndexError: list index out of rang
# 运行到[1,2,3][100]遇到索引错误,抛出错误信息,程序立即终止,之后的'top'不会打印
1.1、异常处理的三个特征
- 异常处理的追踪信息
2)异常的类/类型
3)异常的内容,异常的值
2、为何要处理异常
为了增强程序的健壮性(robust),本来程序一旦出现异常就整体结束掉了,有了异常处理以后,在被检测的代码块出现异常时,被检测的代码块中异常发生位置之后的代码将不会执行,取而代之的是执行匹配异常的except子代码块,其余代码均正常运行,我们也可以将异常信息记录到日志内。
3、如何处理异常
异常总体可以分为两种:语法错误和逻辑错误
3.1 语法错误(SyntaxError)
语法错误是一种低级的错误,我们在写代码的时候应尽量避免。
处理方法:在程序运行前就改正
如:
#if判断,判断条件后缺少冒号:
if 3>1
print('run...')
#SyntaxError: invalid syntax
#在运行前改正
if 3>1:
print('run...')
3.2 逻辑上的错误
每个人的逻辑不可能永远一丝不漏,都可能出现纰漏,所以这种逻辑上的错误我们可能经常遇到,而且这种错误我们事先不知道。
#1)
print(x)
#NameError: name 'x' is not defined
#2)
l=[1,2]
print(l[111])
#IndexError: list index out of range
#3)
1/0
#ZeroDivisionError: division by zer
#4)
int('abc')
#ValueError: invalid literal for int() with base 10: 'abc'
#5)
dic={'age':18}
print(dic['sex'])
#KeyError: 'sex'
#6)
class Foo:
pass
Foo.x
#AttributeError: type object 'Foo' has no attribute 'x'
针对逻辑上的异常处理方式可以分为两种:
3.2.1 如果错误是可以预知的,使用if判断解决
拿猜年龄小程序来说,因为我们无法控制用户的输入,当输入不是数字时就会报错,但是这种错误我们可以预知到,使用if判断就能将这种错误规避掉:
age=input('猜猜我的年龄,请输入你猜测的年龄: ').strip()
#加入if判断,根据if判断结果选择运行的代码,避免了报错
if not age.isdigit():
print('您的输入有误,年龄的是数字,请输入数字')
else:
age=int(age)
if age<18:
print('猜小了哦!')
elif age>18:
print('猜大了哦!')
else:
3.2.1 如果错误是我们不能预知,我们就得使用Try/except 异常处理机制来解决
基本的语法为:
# print('start...')
# try:
# # 有可能会抛出异常的代码
# 子代码1
# 子代码2
# 子代码3
# except 异常类型1 as e:
# pass
# except 异常类型2 as e:
# pass
# ...
# else:
# 如果被检测的子代码块没有异常发生,则会执行else的子代码
# finally:
# 无论被检测的子代码块有无异常发生,都会执行finally的子代码
#
# print('end...')
用法一:
print('start')
try:
print('1')
l=['aaa','bbbb']
l[3]
print('2')
xxx
print('3')
dic={'egon':18}
dic['tank']
except IndexError as e:
print('异常信息:',e)
'''
start
1
异常信息: list index out of range'''
# 不会打印2,发生IndexError,之后的代码不在运行,运行except的子代码
用法二:
跟if判断有点相似,第一中异常不满足,继续往下走,其他异常满足,其他异常下的子代码:
try:
print('1')
l=['aaa','bbbb']
# l[3]
print('2')
xxx
print('3')
dic={'egon':18}
dic['tank']
except IndexError as e:
print('异常信息:',e)
except NameError as e:
print('异常信息:',e)
'''
start
1
2
异常信息: name 'xxx' is not defined'''
用法三:
将可能出现的异常类型放到 except后的元组类,类似于or,满足其一,执行子except的子代码:
print('start')
try:
print('1')
l=['aaa','bbbb']
# l[3]
print('2')
# xxx
print('3')
dic={'egon':18}
dic['tank']
except (IndexError,NameError,KeyError) as e:
print('异常信息:',e)
'''
start
1
2
3
异常信息: 'tank' '''
用法四:
except后加else,注意else不能单独与try配合使用,必须要搭配except
,必须放在except之后。只有在被检测的代码块没有触发任何异常的情况下才会执行else的子代码块,
print('start...')
try:
print('1')
print('2')
print('3')
except Exception as e: # 万能异常
print('所有异常都可以匹配的到')
else:
print('====>')
print('end....')
'''
start...
1
2
3
====>
end....'''
用法五:
finally可以单独与try配合使用,无论被检测的代码块是否触发异常,都会执行finally的子代码块,因此通常在finally的子代码块做一些回收资源的操作,比如关闭打开的文件、关闭数据库连接等
f=None
try:
f=open(‘db.txt’,'r',encoding='utf-8')
s=f.read().strip()
int(s) # 若字符串s中包含非数字时则会触发异常ValueError
# f.close() # 若上面的代码触发异常,则根本不可能执行到此处的代码,应该将关闭文件的操作放到finally中
finally:
if f: # 文件存在则f的值不为None
f.close()