在Python中也同样使用try...except...finally...
的错误处理机制
try
except
try:
print('try...')
r = 10/0
print('result:', r)
except ZeroDivisionError as e:
print('except:', e)
finally:
print('finally...')
print('END')
当认为某一块代码有错误时,就可以用try
来运行该段代码,若执行出错,则后续代码不会执行,而会跳转到except
块,执行完except
后,若后续有finally
片段,则执行finally
块
上面的代码中有一个除0的错误,运行结果:
try...
except: division by zero
finally...
END
当计算r后,捕捉到ZeroDivisionError
错误,执行 except
语句段,之后执行finally
else
可以在except
后面加上else
,当没有错误发生时将执行else
语句块
try:
print('try...')
r = 10/5
print('result:', r)
except ZeroDivisionError as e:
print('except:', e)
else:
print('no error')
print('END')
结果:
try...
result: 2.0
no error
END
Python的错误是一个class,所有错误类型都继承自
BaseException
,故使用except
时需注意它会也会捕获该类型的子类。
常见错误类型及继承关系(中文):官方文档
## 优势
使用```try...except```捕获错误还有一个巨大的好处,就是可以跨越多层调用,比如函数```main()```调用```fun()```,```fun()```调用```bar()```,结果```bar()```出错了,这时,只要```main()```捕获到了,就可以处理
```py
def fun(s):
return 10/int(s)
def bar(s):
return fun(s) * 2
def main():
try:
print('try...')
bar('0')
except Exception as e:
print('Error:', e)
finally:
print('finally...')
结果:
try...
Error: division by zero
finally...
栈输出
若错误没有被捕捉,会一直往上抛,最终会被Python解释器捕获,打印一个错误信息,之后程序会退出
文件hello.py
def fun(s):
return 10/int(s)
def bar(s):
return fun(s) * 2
def main():
bar('0')
main()
在Python终端中运行文件,输出:
Traceback (most recent call last): #错误跟踪信息
File "hello.py", line 19, in <module>
main() #错误原因
File "hello.py", line 13, in main
bar('0')
File "hello.py", line 7, in bar
return fun(s) * 2
File "hello.py", line 3, in fun
return 10/int(s)
ZeroDivisionError: division by zero #错误类型
错误信息以栈的形式按顺序输出,由此可以找到错误源头
错误记录
可以使用Python内置的logging
模块记录错误信息
import logging
def fun(s):
return 10/int(s)
def bar(s):
return fun(s) * 2
def main():
try:
print('try...')
bar('0')
except BaseException as e:
logging.exception(e)
finally:
print('finally...')
这样运行,程序会在打印完错误信息后继续运行:
try...
ERROR:root:division by zero
Traceback (most recent call last):
File "hello.py", line 16, in main
bar('0')
File "hello.py", line 10, in bar
return fun(s) * 2
File "hello.py", line 6, in fun
return 10/int(s)
ZeroDivisionError: division by zero
finally...
抛出错误
常常使用raise
函数抛出错误,当前函数不知道怎么处理错误时,将其向上抛,交给上层函数来处理
|raise
语句如果不带参数,就会把当前错误原样抛出。此外在except
中raise
一个Error,还可以把一种类型的错误转化成另一种类型:
try:
10 / 0
except ZeroDivisionError:
raise ValueError('input error!')
只要是合理的转换逻辑即可,但绝不应该将一个IOError
转换成毫不相干的ValueError