学习笔记:Python3 异常处理
异常处理
仅为个人查阅使用,如有错误还请指正。
开发人员在编写程序时,难免会遇到错误,有的是编写人员疏忽造成的语法错误,有的是程序内部隐含逻辑问题造成的数据错误,还有的是程序运行时与系统的规则冲突造成的系统错误,等等。
总的来说,编写程序时遇到的错误可大致分为 2 类,分别为语法错误和运行时错误。
语法错误是开发者疏忽导致的,属于真正意义上的错误,是解释器无法容忍的,因此,只有将程序中的所有语法错误全部纠正,程序才能执行。
运行时错误,即程序在语法上都是正确的,但在运行时发送了错误,程序是要终止的。如果要避免程序退出,可以使用捕获异常的方式获取这个异常的名称,再通过其他的逻辑代码让程序继续运行。
所以高级语言通常都内置了一套try...except...finally...
的错误处理机制,Python也不例外。
实例
try:
print('try...')
r = 10 / 0
print('result:', r)
except ZeroDivisionError as e:
print('except:', e)
finally:
print('finally...')
print('END')
因为我们认为r = 10 / 0
这段代码可能会出错,所以就用try
来运行这段代码,如果执行错误,后续的代码不会执行,而是直接跳转至错误处理代码,即except
语句,执行完except
后,如果有finally
语句块,则执行finally
语句块,至此,执行完毕。以下是执行结果。
try...
except: division by zero
finally...
END
如果r = 0 / 2
,则执行的结果,看以下代码。
try...
result: 0.0
finally...
END
-
多个
except
来捕获不同类型的错误。try: print('try...') r = 10 / int('a') print('result:', r) except ValueError as e: print('ValueError:', e) except ZeroDivisionError as e: print('ZeroDivisionError:', e) finally: print('finally...') print('END')
int()
函数可能会抛出ValueError
,所以我们用一个except
捕获ValueError
,用另一个except
捕获ZeroDivisionError
。 -
BaseException
异常错误其实也是一个class,所有的错误类型都继承自
BaseException
,所有在使用的时候要注意的是,它不但捕获该类型的错误,还把其子类也“一网打尽。 -
跨越多层调用
大致的意思就是,不需要再每个地方都使用异常捕获。再调用的时候进行捕获就可以了。
看下面的例子,不需要再
foo()
函数和bar()
函数里面做异常,直接再mian()
函数里面调用的时候,做个异常处理就够。def foo(s): return 10 / int(s) def bar(s): return foo(s) * 2 def main(): try: bar('0') except Exception as e: print('Error:', e) finally: print('finally...')
-
raise
如果需要在程序中自行引发异常,则应使用 raise 语句,该语句的基本语法格式为:
raise [exceptionName [(reason)]]
在实际调试程序的过程中,有时只获得异常的类型是远远不够的,还需要借助更详细的异常信息才能解决问题。
捕获异常时,有 2 种方式可获得更多的异常信息,分别是:
-
使用 sys 模块中的
exc_info
方法exc_info()
方法会将当前的异常信息以元组的形式返回,该元组中包含 3 个元素,分别为 type、value 和 traceback,它们的含义分别是:1、type:异常类型的名称,它是
BaseException
的子类。2、value:捕获到的异常实例。
3、traceback:是一个 traceback 对象。
import sys try: x = int(input("请输入一个被除数:")) print("30除以",x,"等于",30/x) except: print(sys.exc_info()) print("其他异常...")
当输入0时,程序运行的结果为:
请输入一个被除数:0 (<class 'ZeroDivisionError'>, ZeroDivisionError('division by zero',), <traceback object at 0x000002DFFAE515C8>) 其他异常...
对于第三个元素,traceback对象无法直接看出有关异常的信息,还需要对其做进一步处理。
就需要使用 traceback 模块中的
print_tb
方法。import sys import traceback try: x = int(input("请输入一个被除数:")) print("30除以", x, "等于", 30 / x) except: traceback.print_tb(sys.exc_info()[2]) print("其他异常...")
当输入0时,程序运行的结果为:
请输入一个被除数:0 File "E:/Yao/project/test_file/haha.py", line 6, in <module> print("30除以", x, "等于", 30 / x) 其他异常...
-
使用 traceback 模块中的相关函数
前面提到了
exc_info()
可以获取异常信息之外,还可以使用 traceback 模块,该模块可以用来查看异常的传播轨迹,追踪异常触发的源头。因为在实际的开发中,为了减少冗余代码,一些函数会被多次调用,但是如果出现错误,一时半会不知道是因为哪个功能调用错误,所以需要从根源去发现。
import traceback class SelfException(Exception): pass def main(): firstMethod() def firstMethod(): secondMethod() def secondMethod(): thirdMethod() def thirdMethod(): raise SelfException("自定义异常信息") try: main() except: # 捕捉异常,并将异常传播信息输出控制台 traceback.print_exc() # 捕捉异常,并将异常传播信息输出指定文件中 traceback.print_exc(file=open('log.txt', 'a'))
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· 趁着过年的时候手搓了一个低代码框架
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· 乌龟冬眠箱湿度监控系统和AI辅助建议功能的实现