第十二天

异常

"""
异常
"""
一、异常的定义
# 异常、错误-----问题---导致控制台报错。
# 异常:在程序运行期。出现的问题
# 错误:在编译期出现的问题。语法解析错误。

# 异常的定义:在程序运行时,出现的异常事件,不正常执行的,打乱程序正常流程的问题。意外(例外)
# 在写作业,笔没水了,商店关门早。
# print(1+a) # 编译期就报红,运行出问题,异常
# print(1/0) # 编译期没报错,运行处问题,异常

# 当程序出现异常时, 会在发生异常的位置,创建一个关于异常类型的对象,对象中会包含异常如何产生的信息。
# 当出现异常之后,在程序中会查找处理异常的程序,如果一直没有人处理,会到python解释器
# 如果仍然没有方法处理,那么会报错,这时候程序才真正的停止

二、异常的传播途径
# 处理:“查找异常的过程”,【向上传播】的过程。
# 当异常时在函数中产生,会传播函数的调用者。
# 如果异常是在模块的顶级位置产生,会传播给导入该模块的另一个模块。

# A调用B B 调用C C 调用D D调用E E 位置抛出一个异常
def E():
w=1/0
def D():
E()
def C():
D()
def B():
C()
def A():
B()
A()

三、异常的常见类型
# BaseException :所有异常的最根类 ,最顶级的父类
# Exception:BaseException的子类(扩展类)
# print(1/0)

1. ZeroDivisionError 除数为0

2. NameError: 名字异常:在命名空间中,找不到对于名字
# print(a)

3. TypeError :类型不匹配
# print(1+"a")

4. AttributeError:属性异常
# 写个属性异常作业

5. Indentation:缩进不正常
# a=1
# b=2

6. IndexError:索引异常
# li=[1,2,3]
# print(li[5])

7. UnboundLocaError:局部变量未绑定
# def hello():
# a+=1
# hello()

8.AssertionError :断言异常
# assert 5>50,"谁说的?"

9. ModuleNotFoundError模块不存在异常
# import a

10. KeyError:字典中的key不存在异常
# d={1:"aaa"}
# print(d[2])

11.RecursionError :递归异常:当函数和函数之间调用次数达到上限,就会出现递归异常
# def x():
# x()
# x()

12. StopIteration:终止迭代异常
# li=[1]
# it=li.__iter__()
# print(it.__next__())
# print(it.__next__())

13. ValueError :对值处理错误的时候,产生的异常
# int("an")

14. SyntaxError 语法错误
# print("ddd"

四、 异常的处理
# 捕获异常
# try ... except...
"""
try:
可能产生异常的程序
except 类型1:
补救措施,处理
except 类型2:
补救措施,处理
...
"""
# try except 出现的几种情况:
1. 当try里面的语句没有产生异常:不执行except的任何一个分支,会把整个程序执行完毕。
class ExceptDemo:
def hello(self):
a=0
a+=1

e=ExceptDemo()
try:
e.hello()
except UnboundLocalError:
print("这是一个本地变量没有绑定的异常")
print("try以外的其他模块继续执行")


2. 当try里面的语句发生异常,使用except对异常进行捕获,成功捕获到异常。
# 程序会继续执行try以外的其他模块
# 当程序中出现多个异常,except也对多个异常类型进行了捕获,只会捕获程序的第一个异常

class ExceptDemo:
def hello(self):
# a=0
a+=1
print("this is a test"+a)

e=ExceptDemo()
try:
e.hello()
except UnboundLocalError:
print("这是一个本地变量没有绑定的异常")
except TypeError:
print("这是类型不匹配的异常")
print("try以外的其他模块继续执行")


# 合并异常 : 直接在except中去捕获多个异常类型,使用","分隔
# 当合并的异常有关联关系的时候,才放在一起,否则提示不够清晰。

class ExceptDemo:
def hello(self):
# a=0
a+=1
print("this is a test"+a)

e=ExceptDemo()
try:
e.hello()
except (UnboundLocalError , TypeError):
print("这是一个本地变量没有绑定的异常 或者 类型不匹配的异常")

print("try以外的其他模块继续执行")

3. 当try里面发生了异常,但是except中对于异常无法捕获,会将异常继续向上传播

class ExceptDemo:
def hello(self):
a=0
a+=1
print("this is a test"+str(a))
b=1/0

e=ExceptDemo()
try:
e.hello()
except (UnboundLocalError , TypeError):
print("这是一个本地变量没有绑定的异常 或者 类型不匹配的异常")
except:
print("发生了异常")

print("try以外的其他模块继续执行")

# 当程序中,在所有异常处理的except最后加一个except,不指定任何异常类型,会捕获所有的异常。
# try ... except习惯上放在函数的调用处,为了避免所有跑出异常的情况都适用同一种处理方式
# 这样每个调用者都可以有自己的处理方式
class T2:
def hello(self):
try:
i=1/0
# except ZeroDivisionError:
# print("发生了除数为0的异常")

t2=T2()
try:
t2.hello()
except ZeroDivisionError:
print("t2对象抛出的异常,卡里钱太少,不要了")
t3=T2()
try:
t3.hello()
except ZeroDivisionError:
print("卡被吞了,我需要打电话")
print("其他模块的代码")

# 练习:自己尝试写一段代码,捕捉一些异常,
# 比较一下,在对于SyntaxError IndentationError 属于错误的异常,和其他属于异常的异常,
# 在捕获上的区别,
# 结论:不能捕获语法上的错误
# try:
# print("dd"
# except:
# print("这是一个语法错误")

五、 异常处理的对象
1. 可以使用sys内建模块sys.exc_info(),获得异常信息
import sys
try:
i=1/0
except ZeroDivisionError:
print(sys.exc_info())

2. 在except指定异常类型的后面 as 异常对象名
try:
i=1/0
except ZeroDivisionError as err:
print(err.args)

六、 捕获多个异常
# 可以使用except多个分支,来捕获可能产生的多个异常,但只能匹配一次。
# 如果多个异常之间没有继承关系,那么还可以。
# 如果当前的异常之间存在着继承关系,except分支的顺序就变得很重要。
# 必须按照先捕获子类异常,再捕获父类异常,如果顺序写反,子类异常永远得不到执行

# try:
# 1/0
# except Exception:
# print("这是except处理")
# except ZeroDivisionError:
# print("这是ZeroDivisionError处理")
#

七、 finally 和 else
# finally子句:定义在finally子句的内容,永远会得到执行,不论是否发生异常
# else:只有在try没有抛出异常的时候(没有走except),才会正常执行

# finally:始终执行的功能模块:数据库连接、释放资源
try:
i=1/0
except:
print("除数为0")
else:
print("no except")
finally:
print("永远执行的finally")
print("try 后面的语句")

def fun():
try :
return 1
finally:
return 2
print(fun())

def fun2():
x=1
try:
return x
finally:
x=2
# finally 里面的x不是原来的x

八、 强制抛出异常
# raise 强制抛出异常。 抛出异常给上一级的调用者,不管是不是真的有异常

1. 在except中使用:目的是为了不隐藏异常信息。
class T:
def hello(self):
i=1/0
def A():
t=T()
try:
t.hello()
except ZeroDivisionError:
a=1
print("这是一个除数为0的异常")
raise
A()
print("其他模块的代码")

2. 在try里面使用raise
class T:
def hello(self):
try:
i=1/0
raise ZeroDivisionError("需要继续处理异常信息")
except:
print("除数为0")
t=T()
t.hello()
print("其他模块的代码")

# 假如客户需要输入年龄,年龄>0才能正常注册
def register(age):
if age>0:
print("正常执行注册")
else:
raise ValueError("age的值必须>=0,你的值不正确{}".format(age))

register(-3)
print("其他模块的代码")

九、自定义异常
# 当已有的异常不符合我们的要求,我们可以自定义异常
"""
自定义异常,去继承Exception类,扩展子类
__init__
__str__
"""
class MyException(Exception):
def __init__(self,value):
self.value=value
try :
raise MyException("这是自定义的异常")
except MyException as err:
print(err.value)

# 练习:自定义一个异常,写一个注册的函数,输入一个年龄,如果输入的年龄大于零,就能注册成功
# 否则就返回异常,重新输入,>0异常自己去定义,ValueError可以捕获非整数异常
class AgeUnderZeroException(Exception):
def __init__(self,value):
self.value="年龄异常,"+value
def register(age):
if age<=0:
raise AgeUnderZeroException("年龄不能小于等于0")

while True:
try:
age=int(input("请输入年龄:"))
register(age)
break
except ValueError:
print("年龄必须是整数值")
except AgeUnderZeroException as ageerror:
print(ageerror.value)




posted on 2018-05-29 09:09  不虚此行ztx  阅读(98)  评论(0编辑  收藏  举报