阅读目录:
1、异常 Exception
2、产生异常
3、异常的捕获
4、异常类及继承层次
5、BaseException及子类
6、Exception 及子类
7、异常的捕获
8、as子句
9、finally 子句
10、异常嵌套
11、else语句
12、异常的捕获时机
13、总结
1、异常 Exception
错误 和 异常的区别:
错误:Error
逻辑错误:算法错误,加法写成了减法
笔误:变量名写错了,语法错误
函数或类使用错误,其实这也属于逻辑错误
总之错误是可以避免的
异常:Exception
本意就是意外情况
这有个前提,没有出现上面说的错误,也就是说程序写的没问题,但是在某些情况下,会出现一些意外,导致程序无法正常的执行下去
例如open函数,操作一个文件,文件不存在,或创建一个文件已经存在,或访问一个网络文件突然断网了,这就是一场,是个意外的情况。
异常是不可能避免的
错误和异常:
在高级编程语言中一般都有错误和异常的概念,异常是可以捕获,并被处理的,但是错误是不能被捕获的。
举例:
异常:
错误:
总结:
一个健壮的程序
尽可能的避免错误
尽可能的捕获,处理各种异常。
Python的特点是,将Error放到异常类中。
2、产生异常:
产生:
raise 语句显式的抛出异常(手动抛出)
Python解释器自己检测到异常并引发它
举例:
解释器自动抛出:
手动抛出:
程序会在异常抛出的地方中断执行,如果不捕获,就会提前结束程序(其实是终止当前线程的执行)
raise:
raise 后面什么都没有,表示抛出最近一个被激活的异常,如果没有被激活的异常,则抛类型异常,这种但是很少使用。
raise 后要求应该是BaseException类的子类或实例,如果是类,将被无参实例化
raise IndexError() :无参构造 ----BaseException的派生类
raise IndexError :无参构造 ----BaseException的派生类
raise IndexError('index error') :有参构造 ----BaseException的派生类
3、异常的捕获:
语法:
1 try:2待捕获异常的代码块,只要出现一条异常,就会终止,后面的执行,跳到except3 except[异常类型]:4 异常的处理代码块
举例:
1:
2:
3:
4、异常类及继承层次:
获取BaseException的子类:
1 def foo(cls, count=0):2 for i in cls.__subclasses__():3 if count ==0:4 print(count * '\t' + '+--' +str(i))5 else:6 print((count - 1) * '\t'+ '|' + '\t' + '+--' +str(i))7 if i.__subclasses__() :8 count += 1
9 foo(i, count)10 else:11 continue
12
13
14 foo(BaseException)
View Code
结果:
1 +--
2 | +--
3 | +--
4 | +--
5 | +--
6 | +--
7 | +--
8 | +--
9 | +--
10 | +--
11 | +--
12 | +--
13 | +--
14 | +--
15 | +--
16 | +--
17 | +--
18 | +--
19 | +--
20 | +--
21 | +--
22 | +--
23 | +--
24 | +--
25 | +--
26 | +--
27 | +--
28 | +--
29 | +--
30 | +--
31 | +--
32 | +--
33 | +--
34 | +--
35 | +--
36 | +--
37 | +--
38 | +--
39 | +--
40 | +--
41 | +--
42 | +--
43 | +--
44 | +--
45 | +--
46 | +--
47 | +--
48 | +--
49 | +--
50 | +--
51 | +--
52 | +--
53 | +--
54 | +--
55 | +--
56 | +--
57 | +--
58 | +--
59 | +--
60 | +--
61 | +--
62 | +--
63 | +--
64 | +--
65 | +--
66 | +--
67 | +--
68 | +--
69 +--
70 +--
71 +--
View Code
5、BaseException及子类
BaseException是所有内建异常类的基类
SystemExit
sys.exit() 函数引发的异常,异常不捕获处理,就直接交给Python解释器,解释器退出。
如果except语句捕获了该异常,则继续向后进行,如果没有捕获,解释器直接退出当前执行的程序
Keyboardinterrupt:
对应的捕获用户中断行为 Ctrl+ c
测试:
本地新建一个.py 文件,输入如下代码:
1 try:2 importtime3 whileTrue:4 time.sleep(2)5 print('_________')6 exceptKeyboardInterrupt:7 print('ctrl + c')8 print('out')
在cmd中执行该文件,可以通过ctrl + c 结束中断。
6、Exception 及子类:
Exception是所有内建的,非系统退出的异常的基类,自定义的异常应该继承他
SyntaxError 语法错误:是无法捕获的,直接识别出来。但在python中是归并到异常类的Exception下的子类
ArithmeticError所有算术引发的异常,其子类有除零异常等。
LookupError:使用映射的键或序列的索引无效时引发的异常的基类:IndexError,KerError
自定义异常:
从Exception继承的类
7、异常的捕获:
except可以捕获多个异常:
总结:
捕获规则
捕获是从上到下依次比较,如果匹配,则执行匹配的except语句块
如果被一个except语句捕获,其他except语句就不会再次捕获了
如果没有任何一个except语句捕获到这个异常,则该异常就向外抛出
捕获原则:
从小到大,从具体到宽泛
8、as子句:
被抛出的异常,应该是异常的实例 ,如何获得这个对象呢,使用as语句。
上面是因为,调用无参构造器,事实上 是有参,但没有缺省值所以在调用的时候,产生异常。
关于 raise 的问题:
一般文件open的都是关于OsError的异常,一般 as e 这个e实例,送到日志中去。
9、finally 子句:
finally:最终,即最后一定要执行的,try-----finally语句快中,不管是否发生了异常,都要执行finally的部分。
测试:return必须写在try语句结构中,如果在最上面,直接返回,函数调用结束了。
一般不这样做,return不会写到 except,finally中,很少这样操作。
如果没有except,就是任何异常都不管,向外抛。
测试嵌套,以及怎么处理文件句柄清理:
raise用法:
测试1:
测试2:
压制异常:使用return
测试1:
测试2:
10、异常嵌套
11、else语句:
12、异常的捕获时机
1、立即捕获:
需要立即返回一个明确的结果。
也就是说,可能产生异常,如果出现异常,立即处理。
1 defparse_int(s):2 try:3 returnint(s)4 except:5 return06 print(parse_int('s'))
2、边界捕获:
封装产生了边界:
例如:写了一个模块,用户调用这个模块的时候,捕获异常,模块内部不需要捕获,处理异常,一番内部处理了,外部调用者就无法感知了。
例如:open函数,出现的异常交给调用者处理,文件存在了,就用在创建了,看是否修改还是删除。
例如:自己写一个雷,使用open函数,但是出现了异常不知道如何处理,就继续往外层抛,一般来说,最外层也是边界,必须处理这个异常了,否则线程退出。
也就是一句话:提供功能的,就不要捕获异常了,往外抛,让调用者感知到异常。让调用者处理。
13、总结:
try:
<> 运行别的代码
except :
<> 捕获某种类型的异常
else:
<> 如果没有发生异常
finally:
<> 退出try 时总会执行
try工作原理:
如果try 中语句执行时发生异常,搜索except子句,并执行第一个匹配该异常的except子句
如果try中语句执行时发生异常,却没有匹配的except子句,异常将被递交到外层的try,如果外层不处理这个异常,异常将继续往外【抛,如果都不能处理,则会传递到最外层,如果还是没有处理,就终止异常所在的线程。
如果try执行时没有发生异常,将执行else语句
无论try中是否发生异常,finally子句最终 都会执行。