python异常处理
一、异常与错误
2、有的错误是用户输入造成的,比如让用户输入email地址,结果得到一个空字符串,这种错误可以通过检查用户输入来做相应的处理。
3、还有一类错误是完全无法在程序运行过程中预测的,比如写入文件的时候,磁盘满了,写不进去了,或者从网络抓取数据,网络突然断掉了。比如在做除法运算时,除数为0等这类错误也称为异常,在程序中通常是必须处理的,否则,程序会因为各种问题终止并退出。
#除法运算 def div(a,b): return a/b x=div(5,0) print(x) #运行出错,ZeroDivisionError: division by zero
Python内置了一套异常处理机制,来帮助我们进行错误处理。
二、python的异常机制
1、语法格式:
try: 语句块1 except Exception as e: #给异常起了个变量名e 语句块2 #多个异常处理方法 #except (异常1,异常2) as e: #多个异常,用元组 # 语句块3 else: #如果语句块1没出现异常,直接执行语句块4, 语句块4 finally: #最终都会被执行的代码 语句块5
2、python的异常机制主要依赖 try 、except 、else、finally 和 raise 五个关键字:
- try 关键字后缩进的代码块简称 try 块,它里面放置的是可能引发异常的代码
-
在 except 后对应的是异常类型和一个代码块,用于表明该 except 块处理这种类型的代码块
- 在多个 except 块之后可以放一个 else 块,表明程序不出现异常时还要执行 else 块
-
最后还可以跟一个 finally 块,finally 块用于回收在 try 块里打开的物理资源,异常机制会保证 finally 块总被执行
-
raise 用于引发一个实际的异常,raise 可以单独作为语句使用,引发一个具体的异常对象
3、异常处理语句块的执行流程
4、异常底层处理
当python解释器收到异常对象时,会寻找能处理异常对象的except块
5、else语句
在 Python 的异常处理流程中还可添加一个 else 块,当 try 块没有出现异常时,程序会执行 else 块。只有当 try 块没有异常时才会执行 else 块,那么为什么不直接把 else 块的代码放在 try 块的代码后面?
当 try 块没有异常,而 else 块有异常时,放在 else 块中的代码所引发的异常不会被 except 块捕获。
6、finally语句
在异常处理语法结构中,只有 try 块是必需的,也就是说:
- 如果没有 try 块,则不能有后面的 except 块和 finally 块;
-
except 块和 finally 块都是可选的,但 except 块和 finally 块至少出现其中之一,也可以同时出现;
- 不能只有 try 块,既没有 except 块,也没有 finally 块;
-
可以有多个 except 块,但捕获父类异常的 except 块应该位于捕获子类异常的 except 块的后面;
- 多个 except 块必须位于 try 块之后,finally 块必须位于所有的 except 块之后。
在通常情况下,不要在 finally 块中使用如 return 或 raise 等导致方法中止的语句,在 finally 块中使用了 return 或 raise 语句,将可能会导致 try 块、except 块中的 return、raise 语句失效。
def demo(a,b): try: x=a/b except ZeroDivisionError: return '除数不能为0' else: return x finally: return 'good-bye' #如果函数里有finally,finally里的返回值会覆盖之前的返回值 print(demo(1,0)) #运行结果:good-bye print(demo(2,4)) #运行结果:good-bye
- 这两条语句都会导致该方法立即结束,那么系统执行这两条语句并不会结束该方法,而是去寻找该异常处理流程中的 finally 块
-
如果没有找到 finally 块,程序立即执行 return 或 raise 语句,方法中止
- 如果找到 finally 块,系统立即开始执行 finally 块,当 finally 块执行完成后,系统才会再次跳回来执行 try 块、except 块里的 return 或 raise 语句
-
如果在 finally 块里也使用了 return 或 raise 等导致方法中止的语句,finally 块己经中止了方法,系统将不会跳回去执行 try 块、except 块里的任何代码。
7、自定义异常
Python 允许程序自行引发异常,自行引发异常使用 raise 语句来完成。
如果需要在程序中自行引发异常,则应使用 raise 语句。raise 语句有如下三种常用的用法:
- raise 单独一个 raise。该语句引发当前上下文中捕获的异常(比如在 except 块中),或默认引发 RuntimeError 异常。
-
raise 异常类:raise 后带一个异常类。该语句引发指定异常类的默认实例。
- raise 异常对象:引发指定的异常对象。
class MyErr(Exception): def __init__(self,m,n): self.m=m self.n=n def __str__(self): return f'长度必须要在{self.m}至{self.n}之间' password=input('请输入密码:') m=6 n=12 if m<=len(password)<=n: print('密码正确!') else: raise MyErr(m,n)
三、python异常使用规范
1、不要过度使用异常
- 把异常和普通错误混淆在一起,不再编写任何错误处理代码,而是以引发异常来代替错误处理。
-
使用异常处理来代替流程控制。
2、不要使用过于庞大的 try 块
- 在 try 块里放置大量的代码,然后紧跟大量的 except 块,增加了编程复杂度。
3、不要忽略捕获到的异常
- 处理异常。对异常进行合适的修复,然后绕过异常发生的地方继续运行;或者用别的数据进行计算,以代替期望的方法返回值;或者提示用户重新操作……总之,程序应该尽量修复异常,使程序能恢复运行。
-
重新引发新异常。把在当前运行环境下能做的事情尽量做完,然后进行异常转译,把异常包装成当前层的异常,重新传给上层调用者。
- 在合适的层处理异常。如果当前层不清楚如何处理异常,就不要在当前层使用 except 语句来捕获该异常,让上层调用者来负责处理该异常。