Python异常处理机制详解:捕获、自定义与最佳实践
本文深入解析Python中的异常处理机制,涵盖异常捕获的基本原理、多分支与通用异常的写法,以及使用raise和自定义Exception类创建特定错误。同时探讨assert断言的使用,并强调合理运用异常处理以提升代码健壮性与可读性的最佳实践。
异常
异常本质上是程序运行过程中出现的错误信号。一旦检测到错误,Python会抛出相应的异常对象,并立即终止当前程序的执行流程。
# 异常处理的三个特征
- 异常的追踪信息
- 异常的类型
- 异常的内容
捕获异常的核心目的在于增强程序的健壮性。即使程序在运行中遭遇错误,通过捕获并妥善处理异常,可以避免程序崩溃,同时将详细的出错信息记录到日志中,便于后续排查。
# 语法上错误SyntaxError
- 处理方式1:必须在程序运行前就改正
# 逻辑上的错误
- 错误发生的条件是可以预知的 --> if判断
- 错误发生的条件是无法预知的 --> 异常捕获 try
在未进行异常处理的情况下,程序遇到错误会直接整体结束。引入异常处理后,当被检测的代码块(try块)中发生异常时,该异常发生位置之后的代码将不再执行,程序控制权转移至匹配的except子代码块。处理完毕后,其余正常代码将继续运行。
异常捕获
当被检测的代码块可能触发多种不同类型的异常时,我们需要针对不同的异常类型采取相应的处理策略。
若希望针对不同异常执行不同的逻辑,应使用多分支的except语句。其工作机制类似于多分支的elif,系统会从上到下依次匹配异常类型,一旦匹配成功,便执行对应的处理逻辑,并跳过后续其他except分支。
try:
# 有可能会抛出异常的代码
子代码1
子代码2
子代码3
except 异常类型1 as e: # as语法将异常类型的值赋值给变量e,这样我们通过打印e便可以知道错误的原因
pass
except 异常类型2 as e:
pass
...
else:
如果被检测的子代码块没有异常发生,则会执行else的子代码
finally:
无论被检测的子代码块有无异常发生,都会执行finally的子代码
# try不能和else单独连用
# try 和 finally 连用,就算出了异常也先执行finally下代码块再抛出异常
若希望将多种不同类型的异常统一用同一种逻辑处理,可以将这些异常类型放入一个元组中,使用单个except语句进行匹配捕获。
try:
被检测的代码块
except (NameError,IndexError,TypeError):
触发NameError或IndexError或TypeError时对应的处理逻辑
若希望捕获所有可能的异常并统一用一种逻辑处理,Python提供了一个通用的万能异常类型Exception。
try:
被检测的代码块
except NameError:
触发NameError时对应的处理逻辑
except IndexError:
触发IndexError时对应的处理逻辑
except Exception:
其他类型的异常统一用此处的逻辑处理
不符合Python解释器语法或逻辑规则的错误,由解释器主动触发各类内置异常。而对于违反程序员自定义规则的情况,则需要由程序员通过raise语句明确触发异常。使用raise时,其后必须跟随一个异常类或异常实例。
class Student:
def __init__(self,name,age):
if not isinstance(name,str):
raise TypeError('name must be str')
if not isinstance(age,int):
raise TypeError('age must be int')
self.name=name
self.age=age
stu1=Student(4573,18) # TypeError: name must be str
stu2=Student('egon','18') # TypeError: age must be int
当内置异常类型无法满足需求时,我们可以通过继承内置的异常类来创建自定义异常类,以表达特定的错误场景。
class PoolEmptyError(Exception): # 可以通过继承Exception来定义一个全新的异常
def __init__(self,value='The proxy source is exhausted'): # 可以定制初始化方法
super(PoolEmptyError,self).__init__()
self.value=value
def __str__(self): # 可以定义该方法用来定制触发异常时打印异常值的格式
return '< %s >' %self.value
class NetworkIOError(IOError): # 也可以在特定异常的基础上扩展一个相关的异常
pass
raise PoolEmptyError # __main__.PoolEmptyError: < The proxy source is exhausted >
raise NetworkIOError('连接被拒绝') # __main__.NetworkIOError: 连接被拒绝
此外,Python提供了断言语句assert expression。该语句用于断定表达式expression成立,若不成立则触发AssertionError异常。其语义等同于raise-if-not,具体用法如下所示。
age='18'
# 若表达式isinstance(age,int)返回值为False则触发异常AssertionError
assert isinstance(age,int)
# 等同于
if not isinstance(age,int):
raise AssertionError
在理解异常处理机制后,部分读者可能出于提高程序容错性和可靠性的目的,倾向于尽可能多地为程序添加try...except...结构。然而,这种做法往往过度消耗了程序的可读性。因为try...except本身是附加给程序的额外逻辑,与核心业务逻辑关系不大。因此,不建议随意使用异常捕获,仅在异常发生不可预知或万不得已时才应使用。
以上就是详解python中的异常捕获的详细内容,更多关于python 异常捕获的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













