24. 错误、调试和测试

try:

try:
	print('try...')
	r = 10 / 0
	print('result:', r)
except ZeroDivisionError as e:
	print('except:', e)
finally:
	print('finally...')
print('END')
  • 从输出可以看到,当错误发生时,后续语句print('result:', r)不会被执行,except由于捕获到ZeroDivisionError,因此被执行。最后,finally语句被执行。然后,程序继续按照流程往下走。
  • 由于没有错误发生,所以except语句块不会被执行,但是finally如果有,则一定会被执行(可以没有finally语句)。
try:
	print('try...')
	r = 10 / int('2')
	print('result:', r)
except ValueError as e:
	print('ValueError:', e)
except ZeroDivisionError as e:
	print('ZeroDivisionError:', e)
else:
	print('no error!')
finally:
	print('finally...')
print('END')
  • 如果没有错误发生,可以在except语句块后面加一个else,当没有错误发生时,会自动执行else语句。

调用堆栈

​ 如果错误没有被捕获,它就会一直往上抛,最后被Python解释器捕获,打印一个错误信息,然后程序退出。

捕获错误的原因

​ 如果不捕获错误,自然可以让Python解释器来打印出错误堆栈,但程序也被结束了。既然我们能捕获错误,就可以把错误堆栈打印出来,然后分析错误原因,同时,让程序继续执行下去。

抛出错误

​ 因为错误是class,捕获一个错误就是捕获到该class的一个实例。因此,错误并不是凭空产生的,而是有意创建并抛出的。

# err_raise.py
class FooError(ValueError):
	pass
def foo(s):
	n = int(s)
	if n==0:
		raise FooError('invalid value: %s' % s)
	return 10 / n
foo('0')

断言

凡是用print()来辅助查看的地方,都可以用断言(assert)来替代。

程序中如果到处充斥着assert,和print()相比也好不到哪去。不过,启动Python解释器时可以用-O参数来关闭assert;关闭后,你可以把所有的assert语句当成pass来看。

logging

把print()替换为logging是第3种方式,和assert比,logging不会抛出错误,而且可以输出到文件。

import logging
# logging.basicConfig(level=logging.INFO)
s = '0'
n = int(s)
logging.info('n = %d' % n)
232/531
print(10 / n)
  • logging.info()就可以输出一段文本。运行,发现除了ZeroDivisionError,没有任何信息。

  • import logging之后添加一行配置后

    $ python3 err.py
    INFO:root:n = 0
    Traceback (most recent call last):
    	File "err.py", line 8, in <module>
    		print(10 / n)
    ZeroDivisionError: division by zero
    

    logging的好处,它允许指定记录信息的级别,有debug,info,warning,error等几个级别

posted @ 2020-08-28 15:41  马里奥本奥  阅读(110)  评论(0编辑  收藏  举报