Python错误处理

在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语句如果不带参数,就会把当前错误原样抛出。此外在exceptraise一个Error,还可以把一种类型的错误转化成另一种类型:

try:
    10 / 0
except ZeroDivisionError:
    raise ValueError('input error!')

只要是合理的转换逻辑即可,但绝不应该将一个IOError转换成毫不相干的ValueError

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus