1.介绍 异常在程序中无处不在,也无法避免,如果不妥善处理潜在的异常,可能会导致整个程序的退出,在Python
中使用try...except
来捕获异常,从而避免程序退出或者不能正常运行。
1.1 不捕获示例 def demo (a: int , b: int ) -> float : return a / bif __name__ == "__main__" : res = demo(10 , 0 ) print ("res = " ,res) Traceback (most recent call last): File "/Users/liuqh/ProjectItem/PythonItem/python-learn-demo/main.py" , line 10 , in <module> res = demo(10 , 0 ) ^^^^^^^^^^^ File "/Users/liuqh/ProjectItem/PythonItem/python-learn-demo/main.py" , line 5 , in demo return a / b ~~^~~ ZeroDivisionError: division by zero
1.2 捕获示例 def demo (a: int , b: int ) -> float : return a / bif __name__ == "__main__" : try : res = demo(10 , 0 ) except ZeroDivisionError: res = None print ("不能除以0" ) print ("res = " , res) 不能除以0 res = None
2. 捕获语法 2.1 常见语法 Python
支持多种组合方式捕获异常,一般我们常见的捕获语法如下:
2.2 常见内置异常对象
异常对象
说明
Exception
通用错误,一般都能用
AttributeError
访问某个对象不存在的属性时
FileNotFoundError
文件不存在
IndexError
索引超过范围错误
KeyError
访问字典中不存在的key
ZeroDivisionError
除数为0错误
NameError
访问的变量未曾定义
TypeError
数据类型错误
SyntaxError
代码语法错误
3.捕获异常方式 3.1 try..except
这种方式是最基本的捕获方式,最开始部分已经演示,这里直接跳过。
3.2 加个 else
3.2.1 捕获语法
3.2.2 代码示例 if __name__ == "__main__" : try : res = demo(10 , 2 ) except ZeroDivisionError: res = None print ("不能除以0:" ) else : print ("代码运行正常" ) print ("res = " , res)
@示例中的demo
函数参见上个示例,这里不在重复.
3.3 多个except
当我们的程序复杂以后,可能会出现各种错误,不一定哪种错误先触发,这个时候我们就需使用多个except
去捕获
3.3.1 捕获语法 try : except 异常对象A: except 异常对象B: except 异常对象C:
3.3.2 代码示例 if __name__ == "__main__" : try : print ("具体代码逻辑....." ) except KeyError: print ("key不存在" ) except FileNotFoundError: print ("文件不存在" ) except Exception: print ("未知错误" ) print ("运行完成" )
@注:捕获多个异常,也可以使用一个except,如except(异常对象A,异常对象B,…):
3.4 加个finally
3.4.1 捕获语法 try : except 异常对象A: finally :
3.4.2 代码示例 if __name__ == "__main__" : try : print ("打开文件,读取内容.." ) demo(1 , 0 ) except Exception as e: print ("发生未知错误: " + str (e)) finally : print ("关闭文件" ) print ("运行结束" )
4. 抛出异常方式 在开发过程中不但要捕获异常,有时也需要我们主动抛出异常,在Python
中,使用关键字raise
抛出异常,语法如下:
4.1 抛出内置错误 def demo (a: int , b: int ) -> float : if b == 0 : raise Exception("参数错误,分母不能为0~" ) return a / bif __name__ == "__main__" : try : demo(1 , 0 ) except Exception as e: print ("运行异常: " + str (e)) print ("运行结束" )
4.2 抛出自定义错误 在实际开发过程中,有时我们需要抛出自定义的错误,用来和内置错误进行区分,示例代码如下:
class MyError (Exception ): pass def demo (a: int , b: int ) -> float : if b == 0 : raise MyError("参数错误,分母不能为0~" ) return a / bif __name__ == "__main__" : try : demo(1 , 0 ) except MyError as e: print ("运行异常: " + str (e)) print ("运行结束" )
5. 具体错误位置 有时候虽然我们捕获了异常,但是却不能准确的定位到具体哪一行代码,Python
提供了traceback
包,用来解决这个问题。
5.1 使用示例 from common import demodef testError (a: int , b: int ) -> float : print ("运行到testError;a :{} b:{}" .format (a, b)) add = a + a return demo.divide(add, b) def divide (a: int , b: int ) -> float : print ("运行到divide;a :{} b:{}" .format (a, b)) if b == 0 : raise Exception("参数错误,分母不能为0~" ) return a / b import tracebackfrom basis import errorif __name__ == "__main__" : try : r = error.testError(10 , 0 ) print (r) except Exception as e: print ("运行异常: " , traceback.format_exc()) print ("运行结束" ) 运行到testError;a :10 b:0 运行到divide;a :20 b:0 运行异常: Traceback (most recent call last): File "/Users/liuqh/ProjectItem/PythonItem/python-learn-demo/main.py" , line 8 , in <module> r = error.testError(10 , 0 ) ^^^^^^^^^^^^^^^^^^^^^^ File "/Users/liuqh/ProjectItem/PythonItem/python-learn-demo/basis/error.py" , line 15 , in testError return demo.divide(add, b) ^^^^^^^^^^^^^^^^^^^ File "/Users/liuqh/ProjectItem/PythonItem/python-learn-demo/common/demo.py" , line 15 , in divide raise Exception("参数错误,分母不能为0~" ) Exception: 参数错误,分母不能为0 ~