学习笔记: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'))
    
原文地址:https://www.cnblogs.com/lowkeyao/p/11311840.html