python异常处理

异常

一般情况下在python无法正常处理程序时就会发生一个异常。
异常是python对象,表示一个错误。当python程序发生错误时需要捕获处理,否则程序会终止执行。

异常处理

捕获异常可以使用try/except语句。

该语句用来检测try语句块中的错误,从而让except语句捕获异常信息并处理。

  • 语法规则

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    try:
    <语句> #运行别的代码
    except <名字>:
    <语句> #如果在try部份引发了'name'异常
    except <名字>,<数据>:
    <语句> #如果引发了'name'异常,获得附加的数据
    else:
    <语句> #如果没有异常发生
    finally:
    <语句> #不管如何,最后一定执行的代码
  • 处理流程
    当开始一个try语句后,python会在当前程序的上下文中进行标记,这样当异常出现时就可以回到这里,try子句先执行,接下来发生什么依赖于执行时是否出现异常。

  1. 当try后面的语句执行出现异常,python就会调回try并执行第一个匹配该异常的except子句,异常处理完成,然后控制流通过整个try语句。
  2. 当try后面的语句执行出现异常,却没有匹配的except子句,异常将会被递交到上层的try,或者到程序的最上层(也就是结束程序,并打印出缺省的出错信息)。
  3. 当try子句执行没有异常,python将执行else后面的语句,然后控制流通过整个try语句。

    实例

  • 有异常出现被捕获的情况
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    try:
    print("开始计算")
    result = 2/0
    print("计算结果为:{0}".format(result))
    except Exception as e:
    print("除数不能为0")
    else:
    print("无异常出现")
    finally:
    print("done")

输出结果

1
2
3
开始计算
除数不能为0
done

根据输出结果可以看到,有异常出现的时候,先执行try语句,遇到异常则停止执行下面的语句(print("计算结果为:{0}".format(result))未执行),跳转至错误处理代码,也就是except语句块,执行完except后执行finally语句块。不执行else语句块。

  • 无异常出现情况
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    try:
    print("开始计算")
    result = 2/1
    print("计算结果为:{0}".format(result))
    except Exception as e:
    print("除数不能为0")
    else:
    print("无异常出现")
    finally:
    print("done")

输出结果

1
2
3
4
开始计算
计算结果为:2.0
无异常出现
done

根据输出结果可以看到,无异常出现的时候先后执行了tryelsefinally语句块,未执行except语句块。
在异常处理时elsefinally语句块可以没有。

  • raise抛出错误
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    try:
    print("开始计算")
    result = 2/0
    print("计算结果为:{0}".format(result))
    except Exception as e:
    print("除数不能为0")
    raise e #添加raise语句抛出错误
    else:
    print("无异常出现")
    finally:
    print("done")

输出结果

1
2
3
4
5
6
7
开始计算
除数不能为0
done
Traceback (most recent call last):
File "<stdin>", line 7, in <module>
File "<stdin>", line 3, in <module>
ZeroDivisionError: division by zero

通过添加raise抛出错误,我们可以看到错误类型为ZeroDivisionError
在python中内置了很多的错误类型,我们可以通过针对不同的错误类型,可以使用不同的except语句处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
try:
print("开始计算")
result = 2/int('a')
print("计算结果为:{0}".format(result))
except ZeroDivisionError as e:
print("除数不能为0")
raise e
except ValueError as e:
print("ValueError")
raise e
else:
print("无异常出现")
finally:
print("done")

输出结果

1
2
3
4
5
6
7
开始计算
ValueError
done
Traceback (most recent call last):
File "<stdin>", line 10, in <module>
File "<stdin>", line 3, in <module>
ValueError: invalid literal for int() with base 10: 'a'

此时执行try语句块时,int()函数抛出ValueError异常,所以执行了第二个except捕获对应异常信息。
前面我们在except中直接使用Exception,由于大部分的错误类型都是继承自该类型,所以可直接捕获其子类。
python中所有的错误都是从BaseException类派生的,点击查看常见的错误类型和继承关系

异常信息规范输出

在常见的前后端分离开发环境中,对于异常信息通常都是按照约定格式,返回json字符串,从而将异常信息记录下来。
下面是一个示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import json

def log():
result = {}
try:
print(2/0)
except Exception as e:
result["msg"] = "Division can not be 0"
result["code"] = 250
result["data"] = [{"a": 1}, {"b": 2}]
finally:
return json.dumps(result) #字典转换为json串

if __name__ == '__main__':
print(log())

输出结果

1
{"msg": "Division can not be 0", "code": 250, "data": [{"a": 1}, {"b": 2}]}

Recommended Posts