异常处理
1. 认识异常处理: 语法分为两种错误,语法错误和异常错误.语法错误是没有按照规定语法写代码,异常错误是在代码语法正确的情况下发生报错.
# (1) IndexError: 索引超出序列的范围 lst = [1,2,3] print(lst[5]) # IndexError: list index out of range # (2) KeyError: 字典中查找一个不存在的键 dic = {"a":1,"b":2} print(dic["c"]) KeyError: 'c' # (3) NameError: 尝试查找一个不存在的变量 # print(aaa) # NameError: name 'aaa' is not defined # (4) IndentationError: 缩进错误 print("缩进") # IndentationError: unexpected indent # (5) AttributeError: 访问未知的属性 class Tree(): name = "bob" obj = Tree() print(obj.age) # AttributeError: 'Tree' object has no attribute 'age' # (6) StopIteration 迭代器没有更多的值 it = iter(range(2)) next(it) next(it) next(it) # StopIteration # (7) AssertionError: 断言语句失败(测试) 若断言正确的话不做任何处理 assert 3>4 # AssertionError ... EOFError 用户输入文件末尾标志EOF(Ctrl+d) FloatingPointError 浮点计算错误 GeneratorExit generator.close()方法被调用的时候 ImportError 导入模块失败的时候 KeyboardInterrupt 用户输入中断键(Ctrl+c) MemoryError 内存溢出(可通过删除对象释放内存) NotImplementedError 尚未实现的方法 OSError 操作系统产生的异常(例如打开一个不存在的文件) OverflowError 数值运算超出最大限制 ReferenceError 弱引用(weak reference)试图访问一个已经被垃圾回收机制回收了的对象 RuntimeError 一般的运行时错误 SyntaxError Python的语法错误 TabError Tab和空格混合使用 SystemError Python编译器系统错误 SystemExit Python编译器进程被关闭 TypeError 不同类型间的无效操作 UnboundLocalError 访问一个未初始化的本地变量(NameError的子类) UnicodeError Unicode相关的错误(ValueError的子类) UnicodeEncodeError Unicode编码时的错误(UnicodeError的子类) UnicodeDecodeError Unicode解码时的错误(UnicodeError的子类) UnicodeTranslateError Unicode转换时的错误(UnicodeError的子类) ValueError 传入无效的参数 ZeroDivisionError 除数为零
2. 异常处理的基本语法: try...except... 防止异常错误,终止程序
try: lst = [1,2,3] print(lst[5]) except: pass # 无报错,也无结果 try: lst = [1, 2, 3] print(lst[5]) except: print("抑制异常") #抑制异常 无报错 # 带有分支条件的异常处理 try: print(aaa) lst = [1, 2, 3] print(lst[5]) dic = {} print(dic["a"]) except IndexError: print("索引错误") except NameError: print("没有定义的变量") except KeyError: print("键错误") # 没有定义的变量 返回第一个异常的值后结束程序 def mygen(): yield 1 yield 2 return "生成器" gen = mygen() try: res = next(gen) res = next(gen) res = next(gen) except StopIteration as e: print(e) # 生成器 系统中用__str__魔术方法接收生成器中的返回值 #(1) 其他异常处理的方式: # try...finally 不管是否出现异常,finally里面的代码都会执行 try: print(aaa) finally: print(111) print(222) # NameError: name 'aaa' is not defined # 111 # 222 # (2) try...except...else 如果代码报错,就不执行else分支,如果代码不报错,就执行else分支 try: print(aaa) except: pass else: print("正常执行") # 代码存在异常,无任何打印 try: aaa = 111 print(aaa) except: pass else: print("正常执行") # 代码无异常 # 111 # 正常执行 # (3) for 和while也有else的分支,如果遇到break,则不执行else代码块 for i in range(8): if i == 5: break else: print("正常执行") # 遇到break for i in range(4): if i == 5: break else: print("正常执行") # 正常执行
3. 主动抛出异常: raise 使用方式:raise+异常错误类 或者 raise+异常错误类对象
# BaseException是所有异常类的父类 # Exception是所有常规异常类的父类 try: raise BaseException except: print("111") # 111 # 可简写,默认都是继承BaseException try: raise except: print(111) # 111 # 自定义异常类: #(了解)系统底层获取行数和文件名的函数( 只有在程序异常时才能触发 ) def return_errorinfo(n): import sys f = sys.exc_info()[2].tb_frame.f_back if n==1: return str(f.f_lineno) #返回当前行数 elif n == 2: return f.f_code.co_filename #返回文件名 # 只有在抛出错误的时候,里面的行号和文件名才能获取到 def get_value(n): try: raise except: return return_errorinfo(n) class MyException(BaseException): def __init__(self,num,msg,line,file): # 错误号,错误信息,错误行号,错误文件 self.num = num self.msg = msg self.line = line self.file = file A = 200 try: if A != 100: raise MyException(404,"A是常量,已定义为100,不能更改",get_value(1),get_value(2)) except MyException as e: print(e.num) print(e.msg) print(e.line) print(e.file)
def paly(): print("给你两个选择:A或者B") print("不管是哪个选择,都是有惊喜的,但是相信我,最后你都会选择B") global choise choise = input("请选择") paly() try: if choise != "B": raise except: print("B") print("我说对了吧!你的选择果然是B,真听话") else: print("B") print("我说对了吧!你的选择果然是B,真听话")