Python 异常处理
Python 异常处理
错误类型
-
语法错误(Syntax errors)
代码编译时的错误,不符合Python语言规则的代码会停止编译并返回错误信息
-
异常(Exceptions)
相较于语法错误,异常比较难发现,因为它只在代码运行时才会发生, 如类型错误、数值错误、索引错误和属性错误等。
-
语法错误包含在异常基类中
Python与Java异常类层级区别
语法错误( SyntaxError )
缺少起始符号或结尾符号(括号、引号等)
缩进错误
关键词拼写错误
异常
异常通常由以下问题引起
-
在定义函数之前就引用该函数
-
调用不属于某个对象的方法或者属性
-
试图将某个值转换为不恰当的数据类型
六种典型的异常
除零错误(ZeroDivisionError):除数为0
名称错误(NameError):变量使用前未进行申明或者初始化
类型错误(TypeError):某些函数或者方法只适用于特定的数据类型,如果 对数据类型的操作不当,就会产生类型错误
数值错误(ValueError):在输入类型正确的情况下,具体输入值错误
索引错误(IndexError):超出序列长度的索引操作
属性错误(AttributeError):方法或者属性不适用该对象
总结
print("python异常")
# 如果出现了语法错误,代码不会执行
# SyntaxError : 语法错误, idea可以检测出来
# str = "aaa
# print(str)
# if True:
# # IndentationError : 代码结构错误
# print("asda") # print前没有制表符
# 如果出现了异常,在前面的代码可以正常运行
# 代码顺序执行到发生异常的代码结束并报错
# 除0异常
# i = 100 / 0
# print(i)
# NameError : 变量不存在异常
# print(name)
# ValueError : 类型转换成异常
# print(int("java"))
# TypeError : 类型异常
# print("1" + 1)
l = [1, 2, 3]
# IndexError : 下标越界
# print(l[10])
s = "java"
# AttributeError : 属性异常
# s.append("asd")
捕获异常
代码编写环境自带的高亮显示
便于发现常规语法错误
但难于发现异常
程序要遇到异常的时候,往往是直接中断,跳出执行。但是有些时候,我们需 要在遇到异常的时候另外处理,而不是直接停止。
解决方法:
• try...except...语句
• try...except...else语句
• finally子句
try...except...语句
try关键词内执行的是正常代码,当这部分代码出错的时候,会跳过错误代 码后进入 except 关键词内部,执行此部分的代码
try...except...else语句
当在 try...except... 后加入的 else 指,当程序没发生错误时执行的部分
try...except...else...工作原理
finally子句
finally语句是指,无论程序运行对或错,都会执行的部分
try:
# 捕获异常
i = 100 / 0
except(AttributeError) as a:
# 处理异常
print(a)
except(ZeroDivisionError) as a:
print(a)
else:
print("其它异常")
finally:
print("都会执行")
print("代码执行完成") # 异常被处理之后,剩下的代码会执行
accert,with语句
assert关键字
当Expression部分为True时,则正确执行,程序继续下去;当判断为False时,则抛出后面的e错误提示。
在大型的项目中,assert常被用来作为“防御性编程”
# 如果条件为true ,正常运行,如果为false抛出后面的异常
assert 10 > 5, RuntimeError("运行异常")
with语句
有时候打开了文件却忘记关闭,或者是在读取文件过程出错,那么"with"语句能够很好解决关于文件读取、写入的问题
上面的语句等价于
自主控制异常
抛出异常
除了在代码运行出错时触发错误,我们还可以主动控制抛出异常,通过使用 关键词 raise(类似Java语言中的throw)
# 直接抛出异常
raise RuntimeError("异常")
用户自定义异常
自定义异常的原因
Python提供的内建异常不够用
可以预估某个错误的产生
定义异常类
继承于Exception类, 由它开始扩展
自定义异常
自主定义的NotIntError异常类,捕获非整型错误
自定义API异常
在编写API时,定义一个Root Exception根异常,其他异常都继承于根异常
-
好处1:API代码层次更清晰
-
好处2:API与调用程序代码隔离
如:需要做一个链接数据库服务的模块,提供一个connect函数用于链接,链接 可能出现情况:
-
Socket连接超时
-
Socket拒绝连接
使用异常代替返回状态码 聚类分析
编写工具类函数时,函数处理流程会产生很多状态
用返回值代表函数处理状态,调用者需要去理解每个状态码的意义,存在学习成本
利用抛出异常处理代码的优点
增强代码的鲁棒性而不必影响程序的主逻辑,专注程序主逻辑,保持代 码的简洁清晰
异常判断是就地实时的,与代码运行是实时的
一些低调用级别的代码块没有判断和处理其上级调用模块的权限或者根 本无法判断,只能由其上级调用模块来决定下一步怎么做,这时当前模 块可以不用处理,将错误抛出给调用者