python异常处理

python异常处理

       Python提供了非常重要的功能来处理程序运行中出现的异常。在程序运行过程中,由于编码不规范等造成程序无法正常运行,此时程序会报错。

一、异常与错误

       1、有的错误是程序编写有问题造成的,比如本来应该输出整数结果输出了字符串,这种错误我们通常称之为bug,bug是必须修复的。

       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、异常底层处理

       如果在执行try块里的业务逻辑代码时出现异常,系统自动生成一个异常对象,该异常对象被提交给python解释器,这个过程被称为引发(触发)异常。

       当python解释器收到异常对象时,会寻找能处理异常对象的except块

       a、如果找到合适的except块,则把异常对象交给该except块处理,这个过程被称为捕获异常。
       b、如果python解释器找不到捕获异常的except块,则运行终止,python解释器也将退出。
 

       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 块之后。
       不管 try 块中的代码是否出现异常,也不管哪一个 except 块被执行,甚至在 try 块或 except 块中执行了 return 语句,finally 块总会被执行。

       强烈建议:

       在通常情况下,不要在 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 
 
       如果 Python 程序在执行 try 块、except 块时遇到了 return 或 raise 语句
  • 这两条语句都会导致该方法立即结束,那么系统执行这两条语句并不会结束该方法,而是去寻找该异常处理流程中的 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 语句来捕获该异常,让上层调用者来负责处理该异常。
posted @ 2021-02-28 22:20  wangshanglinju  阅读(142)  评论(0编辑  收藏  举报