Python进阶系列—(5)异常处理
一、错误与异常
错误
:代码不符合规范,无法被识别和执行。
异常
:程序语法正确,可以被执行,但是执行过程中遇到了错误,抛出异常。
示例:
#缺少冒号,错误
if name is not None
print(name)
#异常
10 / 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
二、异常处理方法
1、try-except
通常难以保证程序覆盖所有异常类型,可在最后的except block,声明其处理的异常为Exception。
Exception是其他所有非系统异常的基类,能够匹配任意非系统异常。
示例:
try:
s = input('please enter two numbers separated by comma: ')
num1 = int(s.split(',')[0].strip())
num2 = int(s.split(',')[1].strip())
...
except ValueError as err:
print('Value Error: {}'.format(err))
except IndexError as err:
print('Index Error: {}'.format(err))
except Exception as err:
print('Other error: {}'.format(err))
或者在except后省略异常类型,表示与任意异常相匹配(包括系统异常 ):
try:
s = input('please enter two numbers separated by comma: ')
num1 = int(s.split(',')[0].strip())
num2 = int(s.split(',')[1].strip())
...
except ValueError as err:
print('Value Error: {}'.format(err))
except IndexError as err:
print('Index Error: {}'.format(err))
except:
print('Other error')
注意:当程序中有多个except block时,最多只有一个except block会被执行,即最先匹配的block。
2、finally
finally经常与try-except连用,表示无论发生什么状况,finally block中的代码都会被执行,哪怕前面的try和except block中使用了return语句。
示例:文件读取
import sys
try:
f = open('file.txt', 'r')
.... # some data processing
except OSError as err:
print('OS error: {}'.format(err))
except:
print('Unexpected error:', sys.exc_info()[0])
finally:
f.close()
所以在finally中,经常会放一些无论如何都要执行的语句。
3、用户自定义异常
示例:
class MyInputError(Exception):
"""Exception raised when there're errors in input"""
def __init__(self, value): # 自定义异常类型的初始化
self.value = value
def __str__(self): # 自定义异常类型的string表达形式
return ("{} is invalid input".format(repr(self.value)))
try:
raise MyInputError(1) # 抛出MyInputError这个异常
except MyInputError as err:
print('error: {}'.format(err))
三、注意事项
1、在程序中不确定某段代码能否成功执行,则使用异常处理。
示例:json loads。
import json
raw_data = queryDB(uid) # 根据用户的id,返回相应的信息
data = json.loads(raw_data)
2、不可滥用异常处理。
示例:查找字典中键对应的值。
d = {'name': 'jason', 'age': 20}
try:
value = d['dob']
...
except KeyError as err:
print('KeyError: {}'.format(err))
使得代码冗余,且不易阅读。因此对于flow-control(流程控制)的代码逻辑,一般不用异常处理。此处可以使用条件语句或者使用get()方法。
if 'dob' in d:
value = d['dob']
#或者使用get()方法
d.get('dob','null')
3、try block中有多处异常,只使用一个try-except block。
示例:
try:
db = DB.connect('<db path>') # 可能会抛出异常
raw_data = DB.queryData('<viewer_id>') # 可能会抛出异常
except (DBConnectionError, DBQueryDataError) err:
print('Error: {}'.format(err))
try:
db = DB.connect('<db path>') # 可能会抛出异常
try:
raw_data = DB.queryData('<viewer_id>')
except DBQueryDataError as err:
print('DB query data error: {}'.format(err))
except DBConnectionError as err:
print('DB connection error: {}'.format(err))
两者效果相同,但第一种效率更高,且更简介,故选择第一种。