很久没写博客了
什么是异常
异常就是程序运行时发生错误的信号(在程序出现错误时,则会产生一个异常,若程序没有处理它,则会抛出该异常,程序的巡行也随之终止).
- 异常的组成
- 1.追踪信息(具体发生异常的位置 以及函数的调用顺序)
- 2.异常的类型(错误的类型)
- 3.异常的消息(详细的错误信息)
- 异常的分类
- 1.语法异常:就是语法检查时就会报错的异常,这种异常很low,不应该犯
比较好避免
如果用编译器 会自动提示
如果你牛逼到用本文编辑器写,应该不会出现这种错误. - 2.逻辑异常(运行时异常)
这种异常只有在代码被执行时才能发现
我们处理的重点就是逻辑异常
特点:- 在没有运行代码前,无法发现
- 如果运行时异常已经发生并且没有正确处理他 就抛出错误信息 并中断程序的执行 这是要我们学校异常解决的问题
- 1.语法异常:就是语法检查时就会报错的异常,这种异常很low,不应该犯
我们学习异常处理就是为了让我们的程序更加稳定(健壮性) 不容易崩溃
常见异常
常见错误 | 发生原因 |
---|---|
NameError | 找不到变量或函数名 |
ValueError | 在调用函数是给的值不正确 |
TypeError | 类型错误 调用一个不能调用的类型 |
ZeroDivisionError | 除数不能为0 |
KeyError | 没有Key |
IndexError | 索引不存在 |
StopIteration | 没有更多的值可以迭代 |
FileNotFoundError | 文件不存在 |
io.UnsupportedOperation | 文件的操作不支持 |
AttributeError | 没有这个属性 |
KeyboardInterrupt | 程序被强行终止/ctrl+c |
异常处理
处理异常常用语法
try:
'可能出现异常的代码'
except 异常类型:
'当异常发生并且异常类型匹配执行except中的代码'
注意:一旦try中有代码抛出异常,后面的代码全都不执行
- 尝试一下捕捉异常
print("staring.....")
try:
name
except NameError:
print("名字找不到!")
print("end.......")
- 多种异常类型处理,当代码可能出现多种异常时
print("staring.....")
try:
# name
[][-1]
pass
except NameError:
print("名字找不到!")
except IndexError:
print("索引超出范围")
print("end.......")
- 多种异常写法二:
没法判断具体是哪个错误发生
print("staring.....")
try:
{}["aaa"]
# name
# [][-1]
1/0
except (NameError,IndexError,ZeroDivisionError):
print("可能名字找不到! 可能所以超出范围 可能除数为0")
print("end.......")
- 万能异常类型:因为异常类型太多
Exception 或 BaseException 基于OOP的继承和多态
print("staring.....")
try:
# {}["aaa"]
# name
# [][-1]
1/0
except Exception:
print("可能名字找不到! 可能所以超出范围 可能除数为0")
print("end.......")
处理异常不太常用的语法
- 语法一:else
try:
'可能出现异常的代码'
except 异常类型:
'捕捉到异常执行的代码'
else:
'没有发生异常时执行的代码'
如果在try中没有出现异常
print("start...")
try:
# 1/0
#[][1]
pass
except ZeroDivisionError:
print("除数异常")
except NameError:
print("名字异常")
else:
print("else会在 try中没有异常时执行")
print("end...")
你可以尝试,让try里代码出现异常,else中的代码就不会被执行
- 语法二:finally(通常用来回收系统资源)
try:
'可能出现异常的代码'
except 异常类型:
'捕捉到异常执行的代码'
finally:
'无论是否发生异常,都会在发生异常后执行finally'
print("start...")
try:
# 1/0
[][1]
pass
except ZeroDivisionError:
print("除数异常")
except IndexError:
print("索引异常")
else:
print("else会在 try中没有异常时执行")
finally:
print("finally 无论异常是否发生 都会执行!")
print("end...")
可以自己尝试,没有捕捉异常时和没有发生异常时的结果
使用finally来回收资源
try:
f = open(r"D:\上海python全栈4期\day31\异常处理\1今日内容","rt",encoding="utf-8")
f.read()
f.write("123")
except Exception:
print("发生异常了")
finally:
print("关闭文件!")
f.close()
主动抛出异常raise
当程序中有一些限制,然而用户没有遵守时,我们就可以主动抛出异常
- 语法
raise 异常类型('异常的详细信息')
# 类型必须是BaseException的子类
例子:
age = input("请输入整型的年龄:")
if not age.isdigit():
raise TypeError("你输入的不是整型!")
age = int(age)
print("十年后你%s岁" % (age + 10))
断言assert
断言:可以理解为断定,就是很明确
- 什么时候需要断定?
当下面的代码必须依赖上面代码的正确数据是 - 语法
assert 结果给Bool值的表达式
pass
'''
当值为True 则继续执行下面的代码
当值为False 抛出异常 AssertionError 表示断言失败
没有assert 也可以使用if assert仅仅是简化了代码
'''
例子:
li = []
#if len(li) < 1:
# raise ValueError("列表中没有数据!")
assert len(li) > 0
pass
'''
if判断raise抛出异常 和 assert断言都可以用
'''
# 自己运行尝试结果
自定义异常
当系统提供的这些异常类型和你要描述的错误不匹配时,就需要自定义异常类型
- 语法:
class 自定义异常类型名称(BaseException):
pass
自定义异常类型是为了更具体描述你的错误,让使用者一眼就看出来
- 如何自定义异常类型
- 在except中,使用as来获取异常对象
# 自定义异常类
class UnlikeError(BaseException):
def __init__(self,msg):
self.msg = msg
# 函数中可能抛出异常
def hello():
text = input("输入一段话:")
if text == "你真帅":
print("你说得对!")
else:
raise UnlikeError("你再看看...")
# 捕获异常
try:
hello()
# 获取异常对象
except UnlikeError as e:
print(e.text)
什么时候用异常处理
try…except是你附加给你的程序的一种异常处理的逻辑
不应该滥用try except
如果你知道为什么出错,就应该吧代码修改正确
加上try…except会导致你的代码可读性变差
我的老师说:异常处理不是你错误逻辑的擦屁股纸,只有在错误发生的条件无法预知的情况下,才应该加上try…except