一、什么是异常
异常就是程序运行时发生错误的信号(在程序出现错误时,则会产生一个异常,若程序没有处理它,则会抛出该异常,程序的运行也随之终止),在python中,错误触发的异常如下
错误分成两类:
1.语法错误,不按照python的语言规定去写代码,这种比较二逼
2.逻辑错误,这种可能读的少
二、异常的种类
在python中不同的异常可以用不同的类型(python中统一了类与类型,类型即类)去标识,一个异常标识一种错误

AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x IOError 输入/输出异常;基本上是无法打开文件 ImportError 无法引入模块或包;基本上是路径问题或名称错误 IndentationError 语法错误(的子类) ;代码没有正确对齐 IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5] KeyError 试图访问字典里不存在的键 KeyboardInterrupt Ctrl+C被按下 NameError 使用一个还未被赋予对象的变量 SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了) TypeError 传入对象类型与要求的不符合 UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它 ValueError 传入一个调用者不期望的值,即使值的类型是正确的
更多的异常种类

ArithmeticError
AssertionError
AttributeError
BaseException
BufferError
BytesWarning
DeprecationWarning
EnvironmentError
EOFError
Exception
FloatingPointError
FutureWarning
GeneratorExit
ImportError
ImportWarning
IndentationError
IndexError
IOError
KeyboardInterrupt
KeyError
LookupError
MemoryError
NameError
NotImplementedError
OSError
OverflowError
PendingDeprecationWarning
ReferenceError
RuntimeError
RuntimeWarning
StandardError
StopIteration
SyntaxError
SyntaxWarning
SystemError
SystemExit
TabError
TypeError
UnboundLocalError
UnicodeDecodeError
UnicodeEncodeError
UnicodeError
UnicodeTranslateError
UnicodeWarning
UserWarning
ValueError
Warning
ZeroDivisionError
三、异常处理
1.异常是如何被检测到?
python解释器检测到的错误
程序员自己触发的异常,如raise
2.为何要进行异常处理?
增加程序的健壮性与容错性
3.异常处理的情形分类
错误发生的条件是可预知的,用if进行预防:

#第一段代码 age=input(">>>") if age.isdigit(): int(age) elif age.isspace(): print("输入的是空格") elif len(age) == 0: print("输入为空") else: print("其他情况,执行这") #第二段代码 num=input(">>>") if num.isdigit(): int(num) elif num.isspace(): print("输入的是空格") elif len(num) == 0: print("输入为空") else: print("其他情况,执行这") #第三段代码 # ......
这么写也能处理异常,但是if的代码重复了,而且可读性很差,一眼看下去让人懵逼
有人说,那我可以改写成这样:

age=input(">>>") num=input(">>>") if age.isdigit()and num.isdigit(): int(age) int(num) elif ......
那如果我有好几十个变量要判断,你怎么办?
要写成这样吗?if age.isdigit()and num.isdigit() and id.isdigit() and date.isdigit()...
if判断式小结:
只能针对某一段代码,对于不同代码的相同类型的错误你需要写重复的if来进行处理,这就会降低程序的可读性。
if判断式虽然存在以上问题,但是实际上它是能进行异常处理的,所以异常处理不只有try...except

def test(): print("test running") choice_dic={ "l":test } while True: choice=input(">>>").strip() if not choice or choice not in choice_dic:continue #这便是一种异常处理机制 choice_dic[choice]()
错误发生的条件是不可预知的,用到try...except:在错误发生之后进行处理
python为每一种异常定制了一个类型,然后提供了一种特定的语法结构来进行异常处理,其中一种就是try...except
try...except的基本语法结构:
try
被检测的代码块
except 异常类型:
try中一旦检测到异常,就执行这个位置的逻辑
注意:try中一旦在某个位置爆发异常就不再执行该位置后面剩余的代码了,直接执行except里面写好的异常处理语句,防止程序崩掉。
#part1 无分支

try: age=input(">>>") int(age) num=input(">>>") int(num) except ValueError as e: print(e)
#part2 多分支

try: age=input(">>>") int(age) num=input(">>>") int(num) l=[] l[1000] except ValueError as e: print(e) except KeyError as e: print("--->",e) except IndexError as e: print("===>",e) print(123) #异常处理完毕后,此段代码还能执行
#part3 万能异常类

try: age=input(">>>") int(age) num=input(">>>") int(num) l=[] l[1000] except Exception as e: #捕获所有异常 print(e) print(123) #异常处理完毕后,此段代码还能执行
#part4 多分支与万能异常类结合

try: age=input(">>>") int(age) num=input(">>>") int(num) l=[] l[1000] except ValueError as e: print(e) except KeyError as e: print("--->",e) except IndexError as e: print("===>",e) except Exception as e: #以防有疏漏 print(e) print(123)
#part5 异常处理的其他结构

s1 = "ljy" try: int(s1): #引发异常 except ValueError as e: print(e) except KeyError as e: print("--->",e) except IndexError as e: print("===>",e) except Exception as e: print(e) else: print("try内代码没有异常则执行我") #不执行 finally: print("无论异常与否,都会执行该模块,通常做一些清理工作")#执行
#part6 raise主动触发异常

try: raise KeyError("key错误") except Exception as e: print(e)
#part7 自定义异常
要继承异常的基类
不用自己写__str__函数

class LjyException(BaseException): def __init__(self,msg): self.msg=msg # def __str__(self): 自动帮你写__str__ # return self.msg #print(LjyException("自定制异常")) #LjyException("自定制异常")一运行就初始化,msg就传进出去了 try: raise LjyException("自定制异常msg") except LjyException as e:#LjyException运行完之后会自动(__str__的作用)返回msg print(e)
#part8 断言
在程序的某个地方判断某个结果是不是你想要的,如果是你想要的,则执行下面的逻辑,如果不是你想要的,则抛出异常

def test(): "一堆逻辑" res=1 return res res=test() assert res == 2 #这里相当于下面的if判断 # if res !=2: # raise AssertionError print("执行下面的一万行代码")
try...except小结:
try...except可以使程序在不牺牲可读性的前提下增强健壮性和容错性,对于同一种异常,一个except就可以捕捉到,可以同时处理多段代码的异常,减少重复代码,增强可读性
什么时候用try...except
try...except应该少用,因为它本来就是附加的处理逻辑,加多了,可读性也会变差。
而且它不是给你擦屁股用的,只有在有一些不可预知的情况下,才应该用,其他的逻辑错误应该尽量提前修正。