• 学习笔记: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'))
      
  • 相关阅读:
    MySQL
    权限(二)
    权限(一)
    化栈为队
    栈的最小值
    实现简易版react中createElement和render方法
    12.整数转罗马数字
    call,apply,bind的理解
    8. 字符串转换整数 (atoi)
    172.阶乘后的0
  • 原文地址:https://www.cnblogs.com/lowkeyao/p/11311840.html
Copyright © 2020-2023  润新知