Loading

day 34 异常处理

1 什么是异常

  • 异常处理的三个特征

    异常的追踪信息

    异常的类型

    异常的内容

​ 异常是程序发生错误的信号。程序一旦出现错误,便会产生一个异常,若程序中没有处理它,就会抛出该异常,程序的运行也随之终止。在Python中,错误触发的异常如下

img

而错误分成两种,一种是语法上的错误SyntaxError,这种错误应该在程序运行前就修改正确

>>> if  
  File "<stdin>", line 1
    if
     ^
SyntaxError: invalid syntax

另一类就是逻辑错误,常见的逻辑错误如

# TypeError:数字类型无法与字符串类型相加
1+’2’

# ValueError:当字符串包含有非数字的值时,无法转成int类型
num=input(">>: ") #输入hello
int(num)

# NameError:引用了一个不存在的名字x
x

# IndexError:索引超出列表的限制
l=['egon','aa']
l[3]

# KeyError:引用了一个不存在的key
dic={'name':'egon'}
dic['age']

# AttributeError:引用的属性不存在
class Foo:
    pass
Foo.x

# ZeroDivisionError:除数不能为0
1/0

2 为何处理异常

​ 为了增强程序的健壮性,即便是程序运行过程中出错了,也不要终止程序,而是捕捉异常并处理:将出错信息记录到日志内

3 如何处理异常?

​ 为了保证程序的容错性与可靠性,即在遇到错误时有相应的处理机制不会任由程序崩溃掉,我们需要对异常进行处理,处理的基本形式为

3.1 语法上的错误 SyntaxError,

处理方式:必须在程序运行前就改正

 if 1>3
	 print("run...")

3.2 逻辑上的错误

 print(x)
 >>>>>>>>>>>>>>
 l=['a','b']
 l[2]
 >>>>>>>>>>>>>>
 1/0
 >>>>>>>>>>>>>>
 int('abc')
 >>>>>>>>>>>>>>
 dic={'name':'egon'}
 dic['age']
 >>>>>>>>>>>>>>
 class Foo:
	 pass

 Foo.x

针对逻辑上的异常又分成两种处理方式

3.2.1 错误发生的条件是可以预知的,使用 if 判断来解决

 age=input('>>: ').strip() 	# 输入的只要不是数字就会出错

 if age.isdigit():
	 age=int(age)
     if age > 18:
         print('猜大了')
     elif age < 18:
         print('猜大了')
     else:
         print('猜对了')
 else:
	 print('必须输入数字')

3.2.2 错误发生的条件是无法预知的

处理的基本形式为

try:
    被检测的代码块
except 异常类型:
    检测到异常,就执行这个位置的逻辑
 print('start...')

 try:
     #有可能会抛出异常的代码
     子代码 1
     子代码 2
     子代码 3
     
 except 异常类型 1 as e:
 	 pass
 	 
 except 异常类型 2 as e:
	pass
 ...
 else:
 	#如果被检测的子代码块没有异常发生,则会执行 else 的子代码
 finally:
 	#无论被检测的子代码块有无异常发生,都会执行 finally 的子代码
 	
 print('end...')

​ 本来程序一旦出现异常就整体结束掉了,有了异常处理以后,在被检测的代码块出现异常时,被检测的代码块中异常发生位置之后的代码将不会执行,取而代之的是执行匹配异常的except子代码块,其余代码均正常运行。

用法一

基本形式

 print('start...')

 try:
	print('1111111111')
	l=['aaa','bbbb']
	l[3]             # 抛出异常 IndexError,该行代码同级别的后续代码不会运行
	print('2222222222')  
	x
	print('33333333')
	dic={'a':1}
	dic['a']
 except IndexError as e:
	print('异常的信息: ',e)
 	
 print('end....')

用法二

如果我们想分别用不同的逻辑处理,需要用到多分支的except(类似于多分支的elif,从上到下依次匹配,匹配成功一次便不再匹配其他)

 print('start...')

 try:
	 print('1111111111')
	 l=['aaa','bbbb']
	 # l[3]           # 抛出异常 IndexError,该行代码同级别的后续代码不会运行
	 print('2222222222')
	 xxx
	 print('33333333')
	 dic={'a':1}
	 dic['a']

 except IndexError as e:
	 print('异常的信息: ',e)

 except NameError as e:
	 print('异常的信息: ',e)

 print('end....')

用法三

如果我们想多种类型的异常统一用一种逻辑处理,可以将多个异常放到一个元组内,用一个except匹配。如果我们想捕获所有异常并用一种逻辑处理,Python提供了一个万能异常类型Exception

 print('start...')

 try:
	 print('1111111111'
	 l = ['aaa', 'bbbb']
	 l[3]               # 抛出异常 IndexError,该行代码同级别的后续代码不会运行
	 print('2222222222')
	 xxx
	 print('33333333')
	 dic = {'a': 1}
	 dic['aaa']

 except (IndexError, NameError) as e:
 	  print('异常的信息: ', e)
      
 except KeyError as e:
	  print('字典的 key 不存在: ', e)

 except Exception as e:  # 万能异常
	 print('所有异常都可以匹配的到')

 print('end....')

用法四

else 不能单独与 try 配合使用,必须要搭配 except。在多分支except之后还可以跟一个else(else必须跟在except之后,不能单独存在),只有在被检测的代码块没有触发任何异常的情况下才会执行else的子代码块

 print('start...')

 try:
	 print('1111111111')
	 print('2222222222')
	 print('33333333')

 except Exception as e:   # 万能异常
	 print('所有异常都可以匹配的到')

 else:
	 print('====>')

 print('end....')

用法五

finally 可以单独与 try 配合使用。此外try还可以与finally连用,从语法上讲finally必须放到else之后,但可以使用try-except-finally的形式,也可以直接使用try-finally的形式。无论被检测的代码块是否触发异常,都会执行finally的子代码块,因此通常在finally的子代码块做一些回收资源的操作,比如关闭打开的文件、关闭数据库连接等

python try: 被检测的代码块 except 异常类型1: pass except 异常类型2: pass ...... else: 没有异常发生时执行的代码块 finally: 无论有无异常发生都会执行的代码块
 print('start...')

 try:
	 print('1111111111')
	 l = ['aaa', 'bbbb']
	 l[3]                 # 抛出异常 IndexError,该行代码同级别的后续代码不会运行
	 print('2222222222')
	 xxx
	 print('33333333')
	 dic = {'a': 1}
	 dic['aaa']

 finally:                 # 不处理异常,无论是否发生异常都会执行 finally 的子代码
 	print('====》》》》》应该把被检测代码中回收系统资源的代码放到这里')

 print('end....')
posted @ 2021-12-05 22:09  maju  阅读(37)  评论(0)    收藏  举报