十一、异常

一、异常解决
异常定义:Python 中,程序在执行的过程中产生的错误称为异常,如列表索引越界、打开不存在的文件等。
二、捕获异常
2.1 捕获简单异常 (1) 捕获异常 try…except…

try: print('-----test--1---') open('123.txt','r') print('-----test--2---') except IOError: pass

(2)捕获多个异常
#coding=utf-8 try: print('-----test--1---') open('123.txt','r') # 如果123.txt文件不存在,那么会产生 IOError 异常 print('-----test--2---') print(num)# 如果num变量没有定义,那么会产生 NameError 异常except (IOError,NameError): #如果想通过一次except捕获到多个异常可以用一个元组的方式 print('产生错误了')

(3)捕获异常的描述as
#coding=utf-8 try: print('-----test--1---') open('123.txt','r') # 如果123.txt文件不存在,那么会产生 IOError 异常 print('-----test--2---') print(num)# 如果num变量没有定义,那么会产生 NameError 异常except Exception as result: #如果想通过一次ex print(result)

exceptì吾句定义了一个 Exception(所有异常类的父类)的对象 result ,用于接收异常处理对象 打印result 可以输出异常信息,因为程序已经捕获到异常信息,所以不会再出现因为异常而退出的情况
(4)如果没有捕获到异常,那么就执行else中的事情
#coding=utf-8 try: print('-----test--1---') open('123.txt','r') # 如果123.txt文件不存在,那么会产生 IOError 异常 print('-----test--2---') print(num)# 如果num变量没有定义,那么会产生 NameError 异常except Exception as result: #如果想通过一次ex print(result) else: print('没有捕获到异常')

(5)终止行为finally
无论异常是否产生都要执行,常用于释放资源。
try: while True: content = f.readline() if len(content) == 0: break time.sleep(2) print(content) except: #如果在读取文件的过程中,产生了异常,那么就会捕获到 print('捕获到异常') finally: f.close() print('关闭文件')

在程序退出之前,finally从句仍然被执行,把文件关闭。
  • else和finally必须写在except之后,finally需要写在最后,在没有except时else不能和try配合使用,否则会发生语法错误。
三、抛出异常
3.1 使用raise抛出异常 (1)使用类名引发异常
?ralse语句指定异常的类名时,会创建该类的实例对象,然后引发异常。
raise IndexError

(2)使用异常类的实例引发异常
?通过指定创建异常类的实例,直接使用该实例对象来引发异常。
index = IndexError() raise

(3)传递异常
?不带任何参数的 raise 吾句 ,可以再次引发刚刚发生过的异常 ,作用就是向外传递异常。
#coding=utf-8 try: print('-----test--1---') open('123.txt','r') # 如果123.txt文件不存在,那么会产生 IOError 异常 print('-----test--2---') print(num)# 如果num变量没有定义,那么会产生 NameError 异常except (IOError,NameError): #如果想通过一次except捕获到多个异常可以用一个元组的方式 print('产生错误了') raise

(4)指定异常的描述信息
>>> raise IndexError('索引下标超出范围') Traceback (most recent call last): File "", line 1, in IndexError: 索引下标超出范围

(5)异常引发异常
?如果要在异常中抛出另外一个异常,可以使用raise-from语句实现。
>>> try: ...namber ... except Exception as exception: ...raise IndexError('索引下标超出范围') from exception ... Traceback (most recent call last): File "", line 2, in NameError: name 'namber' is not definedThe above exception was the direct cause of the following exception:Traceback (most recent call last): File "", line 4, in IndexError: 索引下标超出范围

(6)捕获所有的异常
try: namber except Exception as exception: print(exception)

3.2 使用assert ?assert 语句又称作断言,指的是期望用户满足指定的条件 当用户定义的约束条件不满足的时候,它会触发 AssertionError 异常,所以 assert 语句可以当作条件式的 ralse 语句 。
assert 逻辑表达式,data# data可选

以上等同于:
a = 0 if not a!=0: raise AssertionError(data)

程序实例:
>>> a = 0 >>> assert a!=0, 'a的值不能为0' Traceback (most recent call last): File "", line 1, in AssertionError: a的值不能为0

assert 语句用来收集用户定义的约束条件,而不是捕捉内在的程序设计错误 因为 Python会自行收集程序的设计错误, 会在遇见错误时自动引发异常。
四、自定义异常
class ShortInputException(Exception): '''自定义的异常类''' def __init__(self, length, atleast): #super().__init__() self.length = length self.atleast = atleastdef main(): try: s = input('请输入 --> ') if len(s) < 3: # raise引发一个你定义的异常 raise ShortInputException(len(s), 3) except ShortInputException as result:#x这个变量被绑定到了错误的实例 print('ShortInputException: 输入的长度是 %d,长度至少应是 %d'% (result.length, result.atleast)) else: print('没有异常发生.')main()

五、预定义清理
?之前在介绍 finally 语句时,说过 finally 语句用于释放资源,如关闭文件等 除了在 finally语句中手动释放资源以外,还可以使用 with 语句预定义清理操作,即无论资源在使用过程中是否发生异常,都会执行释放资源的操作,比如文件使用后自动关闭。
5.1 with 语句
with 语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的"清理"操作,释放资源。
with 文表达式 [as 资源对象]: 对象的操作

上述语法格式表示的含义如下
  • 上下文表达式:返回一个上下文管理器对象。若指定了 as 子句,该对象并不赋值给资源对象,而是将上下文管理器的__enter__()方法的返回值赋值给资源对象。
  • 资源对象:可以是单个变量,也可以是元组
  • 对象的操作 with 语句包裹的代码块。在执行该代码块之前,会调用上下文管理器的__enter__()方法; 在执行代码块之后,会执行__exit__()方法。
5.2 上下文管理器 下面来介绍与上下文管理器有关的概念。
(1)上下文管理协议
??包含__enter_ ()和__exit_() 方法,支持该协议的对象要实现这两个方法 关于这两个方法的介绍如下:
  • __enter __(self) :进入上下文管理器时调用此方法,其返回值被放入 with-as 语句中 as说明符指定的变量中。
  • exit(self type, value, tb): 离开上下文管理器调用此方法 如果有异常- 出现, type、value、tb 分别为异常的类型、值和追踪信息; 如果没有异常,三个参数均设为 None 此方法返回值为 True 或者 False ,分别指示被引发的异常得到了还是没有得到处理,如果返回 False ,引发的异常会被传递出上下文。
【十一、异常】(2)上下文管理器
??支持上下文管理协议的对象,用于实现__enter__()、 exit()方法 ,上下文管理器定义执行with 语句时要建立的运行时上下文 ,负责执行with 语句块上下文中的进入与退出操作。
(3) 运行时上下文
??由上下文管理器创建,通过上下文管理器的_enter_()、 _exit_()方法实现。
(4)上下文表达式
??with 语句中在关键字 with 之后的表达式 该表达式要返回一个支持了上下文管理协议的对象。在了解上下文管理器之后,就能很好地理解with语句的整个执行过程了,具体如下:
  • 首先执行上下文表达式,生成一个上下文管理器对象;
  • 接着,调用上下文管理器__enter__() 方法,如果使用了 as 子句,就把__enter__()方法的返回值赋值给 as 子句中的资源对象;
  • 然后,执行 with 语句包裹的代码块;
  • 无论在执行的过程中是否发生异常,都会执行上下文管理器的__exit__() 该方法负责执行程序的"清理"工作,如释放资源等;
  • 如果执行过程中没有出现异常,或者代码块中执行了 break continue 或者 return 语句,则以 None 作为参数调用__exit__() 方法,如果在执行过程中出现异常,则会使用 sys.exc_info得到的异常信息为参数调用__exit__() 方法;
  • 出现异常时,如果 __exit__()方法返回的结果为 False ,则会重新抛出异常 ,让with之外的语句逻辑来处理异常,这是通用做法; 如果返回 True,则忽略异常,不再对异常进行处理。

    推荐阅读