错误往往可以避免,异常是突发情况,往往不可避免,可以找到异常找一些补救措施
抛出异常如何捕获
由except来捕获异常,后面指定类型就是只捕获什么类型的异常,写的代码健壮性就比较重要
异常类及继承层次
都是从这个类往下走的
系统退出
键盘终止消息
generatorexit
这边才是我们想要的东西
运行时候的异常,递归调用recursionerror
index和key比较接近,属于lokkuperror在搜索过程中的问题
语法异常
这些是常见的,异常是按照继承层次一层层设计好,一般都是运行 过程中直接加载的,供你使用
用这个是捕获不到的,因为是平级的
这么写就抓住了
写0就是一般正常退出的方式
异常被捕获处理后应该继续执行
捕获不到引发异常,什么都不做
这个函数调用,一定会引发系统退出异常,只不过这个异常放了数字,一般是告诉当前调用者,进程退出,给一个值。0表示正常,非0是不正常退出
但是只要用了sys.exit就引发systemexit异常
创建一个文件
还是用cmd试试,服务器的ctrl+c是退出
捕捉键盘ctrl+c,引发中断
exception是所有内建的、非系统退出的异常的基类,自定义异常应该继承自它
语法错误捕捉不到,连编译都没法编译,语法错误都是没法捕捉的
nameerror是它的子类就能找到
语法错误是无法捕获的
自定义异常
子类是父类的类型
打印1没什么问题
打印2
打印3
这个比较是由下而上的,虽然可以捕获多种异常,但是所谓的多种异常,自上而下,只要这个类型属于父类,那么这个类型就可以匹配了,所以indexerror之前就被父类lookup包含了
异常都有继承体系,应该把父类的异常往下写,写多个异常就要关心谁先谁后,祖先类往下写,具体的往上面写,宽泛的往下写
捕获规则,自上而下依次比较
跟if语句类似,一个分支执行其他就不执行了
找不到匹配的程序就中断不再执行,程序崩溃
大部分异常捕获,最后都写这样,如果要捕获ctrl+c就需要写一个keyboardinterrupt
抛出这个异常的无参构造调用,相当于生成一个异常对象,赋值给e,print(e)相当于给e套一个str
name a是没有定义的
定义两个属性
跑到5上面去了
提示缺少参数
产生的无参构造异常就归父类管现在就成功创建异常实例来,抛出了
raise后面并不是什么东西都能放,需要是个异常对象
这就是内部继承的方式
字典等于none,所以想看字典没有
有时候打开文件会有很多异常,比如文件不存在,磁盘满了,就可以直接用oserror来捕获
as语句很简单
处理异常之后,照样执行finally
只要进了try语句块,不管有没有异常finally,是必须执行的
这是有异常的情况下
没有异常的情况下打印了
finally还是执行 了,不受影响
return 3
以前讲过一个函数只有一个return语句,执行了下面的语句就不执行 了,通过返回值告诉是哪个return
5是最后返回值。一般不建议return很多。只有一个return即可
一般很少在try和except写return
有了return,finally照样执行,但是finally一定会执行,只要是在try语句块出现的return语句,对finally是无效的,就算try出现异常,能捕获的捕获。捕获不了,finally都一定会执行
上下文,exit退出是一定会执行的
资源打开了,finally就可以回收资源,上下文的contextmanager装饰器,把含有yield的生成器函数,分割成了一半,插入代码,然后再执行一半,为了保证下一半执行,就放在了finally中,只有这样才能保证函数下半部分绝对会 执行,finally是最后一定要去执行的东西,往往是资源清理释放
打开正常
现在test1文件没有
如果等式右边问题,f就不会存在,下面finally就会出现异常
一般都这么写,close,关闭文件描述符
**f如果不能正常关闭 就什么都不做,这样i就是两层嵌套 **
1/0没有被except捕获,
查看到底finally捕获到了什么异常
管不着这个异常,都不在一个层次上
没有raise该怎么样
现在这样,raise后面什么都不跟就是最后一个语句激活的异常(是file not find还是name error)
这里是可以继续向外抛出异常的
抛出前面最后一个语句激活的异常
这样2个就一起抛出了,类似有一个栈的结构,把2个 异常都放在这里了
了解下raise本质
后面的e相当于再raise一个异常出来
这个相当于异常不处理,直接raise出去
这句话意思就是不管继续向外扔
想要return,需要建立函数
未出现异常
把return去掉试试
这里面的异常就被压制住了
raise和return互相矛盾,只能用 一个
return语句在finally中是有压制异常的效果
这个异常就出不来
这样经常做,把异常做下记录,继续向外抛出
现在这里没什么异常
如果没人管异常,这个return就压制住异常了
抛出的异常就被外面管了
现在就没人管了,异常就从内部抛出了
里面都不管异常,就一直向外抛出
给当前进程结束,直接返回1,说明不正常退出
隔5秒抛出
刚才是如果里面异常没有人管,程序就直接退出了,现在试试能不能导致下面的程序直接退出
异常产生了
产生异常,向调用者处理,如果调用者不处理会向更外层的调用者抛出,遇到最外层,就可以理解到线程了,如果没人管,此线程就直接崩溃了,如果是 工作的主线程,整个进程崩溃 了,这个t就挂掉了
主线程的异常如果处理,主线程就直接崩溃,主线程崩溃则进程崩溃,工作线程崩溃大不了不干活,异常如果处理不了就应该向外层抛出,告诉别人看着办
如果不想让bar函数崩溃就需要对bar函数进行异常处理,想办法把异常解决掉而不是压制掉
子句
现在就打印了
没有异常之后
else子句的意思是没有异常可以执行
try语句,必须有except或者finally
异常是必须处理的东西
推荐这么写
抛出异常会导致所在的线程结束
内层抛出异常,外层可能解决可能不解决
比如写一个处理整数的函数,转换成功是对应的数值,失败就是给0,这个函数就代表需要立即处理这个异常的
open方法,认为自己这个函数是一种封装,如果是提供功能的就往外扔,不要在里面处理,让调用者来决定该如何处理,它不处理就继续向外抛出,直到线程崩溃
在边界可以不处理掉,向边界外抛出,调用者在边界处进行异常的处理
到了最外层,线程,不处理也得处理,否则整个线程就崩溃了
else子句是在没有任何异常发生的时候就执行的
多个是比较常见使用的
非要释放资源可以加finally
退出code只要是非0就认为这个程序是非正常退出,是0就是ok
raise语句可以跑出异常,按照道理with后面可以写也可以不写,不写相当于,抛出最近一个被几乎的异常,如果写东西,要求是必须从baseexception基类继承下来,要写它和它子类的实例
raise后面+类型名,会调用这个类型的无参构造器,来构造一个这个类型的实例对象出来,一切皆对象,抛出来是一个异常对象,as子句吧这个对象用标识符拿到,就可以把里面的信息打印出来,对象里有什么可以用dir看一下,dir可以尽量捕获所有属性,看看里面到底有什么