异常的简介
- 程序在运行过程中不可避免会出现一些错误
- 比如:使用了没有赋值过的变量、除0、使用不存在的索引。。。
- 这些错误在程序中被称为异常
- 程序在运行过程中,一旦出现异常会导致程序立即终止,异常后的代码都不会执行
处理异常
- 程序出现异常,目的并不是要程序立即终止
- python是希望在出现异常时,可以通过编写代码对异常进行处理
**语法:
try:
代码块(可能出现错误的语句)
except:
代码块(出现错误以后的处理方式)
else:
代码块(没有错误时要执行的语句)
try:
print(a)
except:
print('程序出错误了')
else:
print('程序正常运行')
try:
print('hello')
except:
print('程序出错误了')
else:
print('程序正常运行')
# hello
# 程序正常运行
except后面空,就会捕获所有异常,我们可以指定错误类型,出现该种种错误就执行except
try:
print(hello)
except NameError:
print('程序出错误了')
else:
print('程序正常运行')
#程序出错误了
Exception是所有异常的父类,如果exce后跟的是exception,它会捕获所有异常
与except后面为空的区别
- 空只能捕捉一种错误,如果有100个错误类型,就要写100次
- Exception,捕获所有异常,一行搞定。缺点,如果在很有100个错误,返回的都是最先出现的错误,你午饭辨别其他99个错误
try:
lis = (1, 2, 3)
lis[0] = 2
print(20/0)
print(hello)
except Exception as you:
print('错误', you, type(you))
else:
print('程序正常运行')
# 错误 'tuple' object does not support item assignment <class 'TypeError'>
as表示对Exception重新命名
finally
try:
tup = (1, 2, 3)
tup[0] = 2
except NameError:
print('程序出错误了')
except TypeError:
print('我是类型错误')
else:
print('程序正常运行')
finally:
print('无论错不错我都会执行')
如果try里面有两个错误,只会返回第一个错误,因为程序遇到错误就结束了
异常的传播
- 当在函数中出现异常时,如果对函数中对异常进行了除了,则异常不会再传播
- 如果函数中没有对异常进行处理,则异常会继续向函数调用处传播
- 如果函数调用处处理了异常,则不再传播,若没有处理,则继续向调用处传播,直到传递到全局作用域,如果依然没有处理,则程序终止,并显示异常信息。
class abnormal(object):
def error(self):
print(20/0)
a = abnormal()
a.error()
# Traceback (most recent call last):
# File "f:/my_dream/text.py", line 5, in <module>
# a.error()
# File "f:/my_dream/text.py", line 3, in error
# print(20/0)
# ZeroDivisionError: division by zero
ZeroDivisionError上显示,第3和第5行有错误,错误明明在于20/0,但是错误会传播,传给了调度处
- 当程序运行过程中出现异常以后,所有的异常信息会被专门保存到一个异常对象当中
- 而异常传播时,实际上就是异常对象抛给调度处
def error1():
print(20/0)
def error2():
print('我是错误2')
error1()
def error3():
print('我是错误3')
error2()
error3()
# Traceback (most recent call last):
# File "f:/my_dream/text.py", line 10, in <module>
# error3()
# File "f:/my_dream/text.py", line 8, in error3
# error2()
# File "f:/my_dream/text.py", line 5, in error2
# error1()
# File "f:/my_dream/text.py", line 2, in error1
# print(20/0)
# ZeroDivisionError: division by zero
哪里调用,哪里就有毒
自定义异常对象
- 抛出异常可以使用raise语句来抛出异常
- raise语句后面需要跟一个异常类或者是异常的实例
- 抛出异常的目的,告诉调用者这里调用时可能出现问题,希望你自己处理下
class NewError(Exception): # 定义一个异常类,只需继承Exception就可以了
pass
def P_add(a, b):
if a < 0 or b < 0:
raise NewError('出现错误,请输入正数')
r = a+b
return r
f = P_add(-1, 1)
print(f)
# Traceback (most recent call last):
# File "f:/my_dream/text.py", line 9, in <module>
# f = P_add(-1, 1)
# File "f:/my_dream/text.py", line 5, in P_add
# raise NewError('出现错误,请输入正数')
# __main__.NewError: 出现错误,请输入正数
也可以直接在raise后跟Exception,这样就不用在额外定义异常类,
区别在于报错的对象不同
定义了NewError,错误就储存在NewError里