Python学习笔记-异常处理

异常处理

Python Errors and Exceptions 官方文档html

  • 引起异常:
    • 语法: 使用raise 关键字, raise either an exception instance or an exception class (a class that derives from Exception).
      raise NameError('wrong name')
      样例输出:
      Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: wrong name
    • 常见的内置异常类:
      • Exception:
      • AttributeError: 引用属性或给它赋值失败
      • IndexError: 使用了序列中不存在的索引时引起, 为Lookup Error子类
      • KeyError: 使用映射中不存在的索引时引起, 为Lookup Error子类
      • NameError: 找不到对应名称(变量)时引起
      • TypeError: 将内置操做或函数用于类型不正确的对象时引起
      • ValueError: 将内置操做或函数用于这样的对象时引起, 类型正确可是包含的值不对
  • 建立异常(User-defined Exception):
    • 语法: 建立一个异常类, 必需要保证直接或间接的继承Exception父类 Exceptions should typically be derived from the Exception class, either directly or indirectly.
    • 样例: class MyError(Exception): pass
    • 细节:
      • 类尽可能简单, 只须要定义一些关于Error的属性, 方便传给handler进行异常处理
      • 若是在一个module当中须要定义多个Exception Class, 先定义一个BaseError Class, 让其余的subclass Error来继承该BaseError Class: When creating a module that can raise several distinct errors, a common practice is to create a base class for exceptions defined by that module, and subclass that to create specific exception classes for different error conditions:
      • 异常的定义应当以'Error'结尾,这样符合内置异常的命名规范
  • 处理异常
    • 语法: try/except 关键字
    • 样例: try 后面能够接 0个 exception, 1个 exception, 多个exception
      • 0个exception(危险的操做,尽可能避免) 表示一次打包处理全部的异常
      • 1个异常: 只有异常名称对应于try当中抛出的异常时才会被执行
      • 多个异常:
        • 样例: exception (NameError, TrancisionError, ValueError): pass 三个当中任意一个知足时,都会catch并处理
        • 细节: 语法当中的( )不能省略, except RuntimeError, TypeError is not equivalent to except (RuntimeError, TypeError): but to except RuntimeError as TypeError
    • try关键字的执行流程:
      The try statement works as follows.
      First, the try clause (the statement(s) between the try and except keywords) is executed.
      If no exception occurs, the except clause is skipped and execution of the try statement is finished.
      If an exception occurs during the execution of the try clause, the rest of the clause is skipped. Then if its type matches the exception named after the except keyword, the except clause is executed, and then execution continues after the try statement.
      If an exception occurs which does not match the exception named in the except clause, it is passed on to outer try statements; if no handler is found, it is an unhandled exception and execution stops with a message as shown above.python

    • 对except子句当中访问异常对象自己的操做:
      • 为exception instance 命名, 以便于在异常的内部进行调用
      • 为异常对象添加attribute: we can add arguments to the exception. The except clause may specify a variable after the exception name (or tuple). The variable is bound to an exception instance with the arguments stored in instance.args. 必需要对instance命名, 而后才能在以后面进行调用
    • 异常当中的else语句: 执行没有异常时须要作的事情
      The try … except statement has an optional else clause, which, when present, must follow all except clauses. It is useful for code that must be executed if the try clause does not raise an exception. For example:json

try:
    <statements>  # Run this main action first
except <name1>:
    <exc1>           # 当 try中发生了 name1 的异常时运行exc1
except <name2>:
    <exc2>           # 当 try中发生了 name2 的异常时运行exc2
except (<name3>, <name4>:
    <exc3>           # 当 try中发生了 name3 OR name4 的异常时运行exc3
else: 
    <exc4>           # 当代码没有异常时运行exc4
finally: 
    <final>            #无论代码有没有异常都会执行final, 一般用来作一些清理工做
  • 细节: 异常处理当中的几点基本原则:
    • 注意异常的粒度,try当中不该当放入过多的代码,过多的代码会使得异常的定位难以定位, 尽可能只在可能抛出异常的语句块前面放入try语句
    • 谨慎使用单独的except语句处理全部异常, 最好可以定位具体的异常。由于不加具体类型的except可能会掩盖真实的错误
    • 样例:
    import sys
    try: 
        print a
        b = 0
        print a / b
    except:
        sys.exit("ZeroDivisionError:Can not division zero")
    程序打印"ZeroDivisionError: Can not division zero", 可是这不是真正的错误缘由, 真正的错误缘由是a 在使用以前没有进行定义
    • 注意异常的捕获顺序: 小 -> 大 由于异常的捕获是顺序执行的, 小的在前能够直接精肯定位异常, 而大的在前若是锁定不了异常的话, 还要再次执行小的,画蛇添足,大小的划分根据内建异常的继承结构来肯定。原则是若是异常可以在被捕获的位置处理就应当及时的进行处理, 不能处理也应当以合适的方式向上层抛出。向上层传递时使用raise关键字便可。大类错误能够捕捉子类中的错误

【25/91建议】避免finally 可能发生的陷阱:dom

  • 陷阱: 异常屏蔽 OR 设计好的return语句被屏蔽
    • 当finally 语句之中出现了returnbreak语句时, 临时保存的异常 和 try当中本来被设计好的return语句将被丢失
    • 样例:
    def ReturnTest(a):
        try:
            if a <= 0:
                raise ValueError("data can not be negative")
            else:
                return a
        except ValueError as e:
            print e
        finally:
            print("The End!")
            return -1
    
        print ReturnTest(0) # 输出"The End!" "-1" 
        print ReturnTest(1) # 输出"The End!" "-1"  出现问题

finally 当中的return在try 中的else 语句以前执行, 因此会直接运行 finally 当中的return -1 而不是try 当中的 return aide

  • 异常处理模板:
    • try/finally结构: 若是既要将异常向上传播, 又要在异常发生时进行清理工做
    • 样例: read方法抛出的异常会向上传播给调用方, 而finally代码块中的handle.close方法则必定能被执行。open方法必须放在try语句外, 这样若是打开文件时发生异常会跳过finally块
    handle = open('/tmp/random_data.txt') # May raise IOError
    try:
        data = handle.read() # May raise UnicodeDecode Error
    finally:
        handle.close() # Always runs after try
    • try/except/else结构: 清晰描述哪些异常由本身的代码处理、哪些异常会传给上一级。若是try代码中没有发生异常, 那么就执行else语句, 有了这种else 语句, 咱们就能够尽可能缩减try中的代码量。
    • 样例:
    def load_json_key(data, key):
        try:
            result_dict = json.loads(data) # 尝试读取一个JSON文件
        except ValueError as e:
            raise KeyError from e  # 若是代码不是有效的JSON格式, 会产生ValueError
        else:
            return result_dict[key] # 代码是有效的JSOn格式, 进行处理
    • 全套四合一 try/except/else/finally结构
    • 样例:
    def divide_json(path):
    handle = open(path, 'r+')
    try:
        data = handle.read()
        op = json.loads(data)
        value = (
            op['numerator'] /
            op['denominator']) # May raise ZeroDivisionError
    except ZeroDivisionError as e:
        return UNDEFINED
    else:
        op['result'] = value
        result = json.dumps(op)
        handle.seek(0)
        handle.write(result) # May raise IOError
        return value
    finally:
        handle.close() # Always runs
  • 使用内置的logging模块 来记录exception信息
  • 样例:
def main():
    try:
        bar('0')
    except Exception as e:
        logging.exception(e)
相关文章
相关标签/搜索