zoukankan      html  css  js  c++  java
  • 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 语句来捕获该异常,让上层调用者来负责处理该异常。
  • 相关阅读:
    发一段非万能的sql分页代码
    手机版的首页不能翻页,用的是UC7.1
    关于Enterprise library logging中一个没搞明白的东西,希望有大大们进来帮忙释疑一下, THKS
    关于CodeSmith主模板与子模板同时从一个基类继承后的参数传值问题(提供模板下载)
    golang 去除字符串首尾空格
    构建一个SDK的打印信息
    PeekMessage抓取消息,如何把每个消息都获取到呢?
    DirectDraw学习 之 入门(二)
    20111121 —— wince6.0 BSP 里面加了 locale 后编译 failed 之解决办法
    DirectDraw学习 之 编译自带的sample代码
  • 原文地址:https://www.cnblogs.com/shixiaoxun/p/14460887.html
Copyright © 2011-2022 走看看