异常报错的结构认识,如下图所示:
异常的追踪信息显示的出现异常的所在位置,点击即可跳转到该位置
异常的类型,表示该异常的名称
异常说明,python对该异常作出详细的说明,方便作者对异常进行修改

查看异常的技巧:
1.有个报错时时,排错的时候,真正报错的是最下面
2.当报错会出现python代码时,python的代码是不会出错的,应该从下向上找最后一行自己写的代码去处理
常见的异常类型:
1.
a #NameError
2.
sum(1,2,3) #TypeError
3.
dic = {}
dic['key'] #KeyError
4.
l = []
l[1000] #IndexError
5.
l = [1,23]
l_iterator = iter(l)
next(l_iterator)
next(l_iterator)
next(l_iterator) #StopIteration
6.
num = input('num:') 当用户输入非数字时如aaa
int(num) #ValueError
异常处理的特点:
一旦程序发生异常,程序就不在向下执行。
异常处理:
1.异常处理的应用可以用if规避,但是成本太高。如上述异常6,可以使用if进行规避:
num = input('num:')
if num.isdigit():
int(num)
else:
print('请输入数字!')
2.不能用if处理的情况,如 StopIteration异常就不能使用if进行处理
3.异常常规处理方式:使用try except语句进行处理
try:
num = input('num:')
int(num) #ValueError
print(num) #一旦出现异常,此处不会继续执行
except ValueError:
print("请输入一个数字")
print('aaa)
try except总结:放在try中的代码如果遇到except中的错误类型,就会执行except中的代码;且一旦发生异常,try中的代码就会停止在异常处;但不影响try语句之外的代码执行.
try except的方式与if方式的比较:
try..except这种异常处理机制就是取代if那种方式,让你的程序在不牺牲可读性的前提下增强健壮性和容错性;
异常处理中为每一个异常定制了异常类型(python中统一了类与类型,类型即类),对于同一种异常,一个except就可以捕捉到,可以同时处理多段代码的异常(无需‘写多个if判断式’)减少了代码,增强了可读性 ;
使用try..except的方式:
1:把错误处理和真正的工作分开来
2:代码更易组织,更清晰,复杂的工作任务更容易实现;
3:毫无疑问,更安全了,不至于由于一些小的疏忽而使程序意外崩溃了;
多分支except
一般一种错误类型只能处理对应的一种错误,其他错误还会照常报错。解决这种情况可以采用多分支except:
try:
num = input('num:')
int(num) #ValueError
print(num) #一旦出现异常,此处不会继续执行
a #NameError
sum(1,2,3) #TypeError
except ValueError:
print("请输入一个数字")
except NameError as nameerror:
print("产生了一个%s"%nameerror)
except TypeError:
print("产生了一个TypeError")
#as
在我们不能完全明确的知道这个错误到底是发生了什么的时候,就用 as变量名,将变量中存储的错误信息打印出来。
万能异常
try:
a #NameError
sum(1,2,3) #TypeError
dic = {}
dic['key'] #KeyError
l = []
l[1000] #IndexError
l = [1,23]
l_iterator = iter(l)
next(l_iterator)
next(l_iterator)
next(l_iterator) #StopIteration
num = input('num:') 当用户输入非数字时如aaa
int(num) #ValueError
except ValueError:
print("请输入一个数字")
except Exception as e:
print(e)
#对于你已经可以预见的但是不能完全规避的 必须要处理的异常,应该去指定他的处理方式;
#对于其他你不能预料的异常,再使用万能异常处理。
异常处理中的else语句:
try:
a
except NameError as e:
print(e)
else:
print("当try语句中不会发生异常时执行的代码")
finally 在try中无论try出不出现异常,finally语句始终都会执行
def func():
try:
f = open('file')
int(f.read())
except ValueError as e:
print(e)
return 123
finally:
print('before close')
f.close()
print('after close')
print(func())
#当函数return遇到finally时,会继续执行finally中的代码;
finally出现的意义:当程序出现异常时,在异常之前打开的文件或者链接等操作,在程序异常之后不会正常关闭,会造成隐患,使用finally可以执行关闭之前打开的文件或者链接等
简单来说,finally主要做的是"清理工作",把之前打开的链接、文件都关闭,避免程序异常造成的浪费资源和逻辑问题。
finally在装饰器函数中的使用语法:
def wrapper(func):
def inner(*args,**kwargs):
try:
return func(*args,**kwargs)
finally:
"被装饰的函数执行之后要执行的内容"
return inner
else与finally同时使用的情况(一整套应用):
try:
f =open('file')
int(f.read())
except ValueError:
print("读文件失败")
except Exception as e:
print(e)
else:
print("成功了")
finally:
f.close()
主动触发异常-raise
try:
raise TypeError('类型错误')
except Exception as e:
print(e)
断言-assert
assert 1 == 2 #AssertionError
最终总结:
try...except应该尽量少用,因为它本身就是你附加给你的程序的一种异常处理的逻辑,与你的主要的工作是没有关系的;这种东西加的多了,会导致你的代码可读性变差,只有在有些异常无法预知的情况下,才应该加上try...except,其他的逻辑错误应该尽量修正。
附上异常的继承关系:
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StandardError
| +-- BufferError
| +-- ArithmeticError
| | +-- FloatingPointError
| | +-- OverflowError
| | +-- ZeroDivisionError
| +-- AssertionError
| +-- AttributeError
| +-- EnvironmentError
| | +-- IOError
| | +-- OSError
| | +-- WindowsError (Windows)
| | +-- VMSError (VMS)
| +-- EOFError
| +-- ImportError
| +-- LookupError
| | +-- IndexError
| | +-- KeyError
| +-- MemoryError
| +-- NameError
| | +-- UnboundLocalError
| +-- ReferenceError
| +-- RuntimeError
| | +-- NotImplementedError
| +-- SyntaxError
| | +-- IndentationError
| | +-- TabError
| +-- SystemError
| +-- TypeError
| +-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning