• Python try except else(异常处理)用法详解

    Python 的异常处理机制可以让程序具有极好的容错性,让程序更加健壮。当程序运行出现意外情况时,系统会自动生成一个 Error 对象来通知程序,从而实现将“业务实现代码”和“错误处理代码”分离,提供更好的可读性。

    使用try...except捕获异常

    前面章节讲过,希望有一个非常强大的“if 块”,可以表示所有的错误情况,让程序一次处理所有的错误,也就是希望将错误集中处理。

    出于这种考虑,此处试图把“错误处理代码”从“业务实现代码”中分离出来。将上面最后一段伪码改为如下伪码:

    if 一切正常:
        #业务实现代码
    else:
        alert 输入不合法
        goto retry

    上面代码中的“if 块”依然不可表示,因为一切正常是很抽象的,无法转换为计算机可识别的代码。在这种情形下,Python 提出了一种假设,如果程序可以顺利完成,那就“一切正常”,把系统的业务实现代码放在 try 块中定义,把所有的异常处理逻辑放在 except 块中进行处理。

    下面是 Python 异常处理机制的语法结构:

    try:
        #业务实现代码
        ...
    except (Error1, Error2, ...) as e:
        alert 输入不合法
        goto retry

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

    当 Python 解释器收到异常对象时,会寻找能处理该异常对象的 except 块,如果找到合适的 except 块,则把该异常对象交给该 except 块处理,这个过程被称为捕获异常。如果 Python 解释器找不到捕获异常的 except 块,则运行时环境终止,Python 解释器也将退出。

    不管程序代码块是否处于 try 块中,甚至包括 except 块中的代码,只要执行该代码块时出现了异常,系统总会自动生成一个 Error 对象。如果程序没有为这段代码定义任何的 except 块,则 Python 解释器无法找到处理该异常的 except 块,程序就在此退出,这就是前面看到的例子程序在遇到异常时退出的情形。

    下面使用异常处理机制来改写前面章节中五子棋游戏中用户下棋部分的代码:

    inputStr = input("请输入您下棋的坐标,应以x,y的格式:\n")
    while inputStr != None :
        try:
            # 将用户输入的字符串以逗号(,)作为分隔符,分隔成2个字符串
            x_str, y_str = inputStr.split(sep = ",")
            # 如果要下棋的点不为空
            if board[int(y_str) - 1][int(x_str) - 1] != "╋":
                inputStr = input("您输入的坐标点已有棋子了,请重新输入\n")
                continue
            # 把对应的列表元素赋为"●"。
            board[int(y_str) - 1][int(x_str) - 1] = "●"
        except Exception:
            inputStr = input("您输入的坐标不合法,请重新输入,下棋坐标应以x,y的格式\n")
            continue
        ...

    上面程序把处理用户输入字符串的代码都放在 try 块里执行,只要用户输入的字符串不是有效的坐标值(包括字母不能正确解析,没有逗号不能正确解析,解析出来的坐标引起数组越界……),系统就将引发一个异常对象,并把这个异常对象交给对应的 except 块处理。

    except 块的处理方式是向用户提示坐标不合法,然后使用 continue 忽略本次循环剩下的代码,开始执行下一次循环。这就保证了该五子棋游戏有足够的容错性,即用户可以随意输入,程序不会因为用户输入不合法而突然退出,程序会向用户提示输入不合法,让用户再次输入。

    异常类的继承体系

    当 Python 解释器接收到异常对象时,如何为该异常对象寻找 except 块呢?注意上面程序中 except 块的 except Exception:,这意味着每个 except 块都是专门用于处理该异常类及其子类的异常实例。

    当 Python 解释器接收到异常对象后,会依次判断该异常对象是否是 except 块后的异常类或其子类的实例,如果是,Python 解释器将调用该 except 块来处理该异常;否则,再次拿该异常对象和下一个 except 块里的异常类进行比较。

    Python 异常捕获流程示意图如图 1 所示:


    Python 异常捕获流程示意图
    图 1 Python 异常捕获流程示意图

更多...

加载中...