异常
异常就是程序运行时发生错误的信号,在python中,错误触发的异常如下
异常种类
在python中不同的异常可以用不同的类型(python中统一了类与类型,类型即类)去标识,不同的类对象标识不同的异常,一个异常标识一种错误
常见异常:
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x IOError 输入/输出异常;基本上是无法打开文件 ImportError 无法引入模块或包;基本上是路径问题或名称错误 IndentationError 语法错误(的子类) ;代码没有正确对齐 IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5] KeyError 试图访问字典里不存在的键 KeyboardInterrupt Ctrl+C被按下 NameError 使用一个还未被赋予对象的变量 SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了) TypeError 传入对象类型与要求的不符合 UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量, 导致你以为正在访问它 ValueError 传入一个调用者不期望的值,即使值的类型是正确的
异常处理
1.使用if判断式
#我们平时用if做的一些简单的异常处理num1=input('>>: ') #输入一个字符串试试 if num1.isdigit(): int(num1) #我们的正统程序放到了这里,其余的都属于异常处理范畴 elif num1.isspace(): print('输入的是空格,就执行我这里的逻辑') elif len(num1) == 0: print('输入的是空,就执行我这里的逻辑') else: print('其他情情况,执行我这里的逻辑')#这些if,跟代码逻辑并无关系,显得可读性极差,如果类似的逻辑多,那么每一次都需要判断这些内容,就会倒置我们的代码特别冗长。
2.python提供的特定的语法结构
try: # 可能发生异常的代码 except 异常类型1 as 变量名: print(变量名) # 变量名存储的是具体的错误信息 except 异常类型2 as 变量名: print(变量名) # 变量名存储的是具体的错误信息 except Exception as 变量名: print(变量名) # 变量名存储的是具体的错误信息 else: print('如果以上代码没有发生异常以及异常处理工作就执行这里的代码') print('一般情况下else中的代码用来下结论') # logging模块 finally: print('不管代码是否有异常都会执行,且在函数中遇到return仍然会执行') print('一般情况下用于这个函数中资源的回收')
try..except这种异常处理机制就是取代if那种方式,让你的程序在不牺牲可读性的前提下增强健壮性和容错性
异常处理中为每一个异常定制了异常类型(python中统一了类与类型,类型即类),对于同一种异常,一个except就可以捕捉到,可以同时处理多段代码的异常(无需‘写多个if判断式’)减少了代码,增强了可读性
在python的异常中,有一个万能异常:Exception,他可以捕获任意异常。它是一把双刃剑,有利有弊,我们要视情况使用
如果你想要的效果是,无论出现什么异常,我们统一丢弃,或者使用同一段代码逻辑去处理他们,那么只有一个Exception就足够了。
如果你想要的效果是,对于不同的异常我们需要定制不同的处理逻辑,那就需要用到多分支了。我们可以使用多分支+万能异常来处理异常。使用多分支优先处理一些能预料到的错误类型,一些预料不到的错误类型应该被最终的万能异常捕获。需要注意的是,万能异常一定要放在最后,否则就没有意义了。
3.断言
assert断言是声明其布尔值必须为真的判定,如果发生异常就说明表达示为假。可以理解assert断言语句为raise-if-not,用来测试表示式,其返回值为假,就会触发异常。
assert的异常参数,其实就是在断言表达式后添加字符串信息,用来解释断言并更好的知道是哪里出了问题。格式如下:
assert expression [, arguments]
assert 表达式 [, 参数]
assert len(lists) >=5,'列表元素个数小于5'
assert 2==1,'2不等于1'
备注:格式:assert 条件 , 条件为false时的错误信息 结果为raise一个AssertionError出来
# assert 条件 assert 1 == 1 assert 1 == 2