学习目标:
python学习十二、
学习内容:
1、错误处理
2、调试
3、单元测试
4、文档测试
1、错误处理
1、try
错误机制try
- 当错误发生时,后续语句print()不会被执行,except捕获到ZeroDivisionError被执行,finally语句最后执行
try…
except:…
finally…
END
如果有finally,不管有没有错则一定会被执行(可以没有finally语句)
- try的实例
在try机制中,as e意思是把错误信息赋给e,所以打印e就能打印出错误信息
lists = [1,2,3,4]
try:
print(lists[10])
except Exception as e:
print(e)
输出:
list index out of range
except永远也捕获不到UnicodeError,因为UnicodeError是ValueError的子类,如果有,也被第一个except给捕获了
try:
print('try...')
r = 10 / int('2')
print('result:', r)
except ValueError as e:
print('ValueError:', e)
except ZeroDivisionError as e:
print('ZeroDivisionError:', e)
except UnicodeError as e:
print('UnicodeError')
else:
print('no error!')
finally:
print('finally...')
print('END')
- try…except跨层调用
try…except捕获错误可以跨越多层调用
比如函数main()调用bar(),bar()调用foo(),结果foo()出错了,只要main()捕获到了,就可以处理
def foo(s):
return 10 / int(s)
def bar(s):
return foo(s) * 2
def main():
try:
bar('0')
except Exception as e:
print('Error:', e)
finally:
print('finally...')
2、记录错误
当我们找出错误时,就应该能把错误堆栈打印出来
Python内置的logging模块可以非常容易地记录错误信息,同样是出错,但程序打印完错误信息后会继续执行,并正常退出
# err_logging.py
import logging
def foo(s):
return 10 / int(s)
def bar(s):
return foo(s) * 2
def main():
try:
bar('0')
except Exception as e:
logging.exception(e)
main()
print('END')
输出:
ERROR:root:division by zero
Traceback (most recent call last):
File "F:/pycharm/project/ten.py", line 39, in main
bar('0')
File "F:/pycharm/project/ten.py", line 35, in bar
return foo(s) * 2
File "F:/pycharm/project/ten.py", line 32, in foo
return 10 / int(s)
ZeroDivisionError: division by zero
END
3、抛出错误
Python的内置函数会抛出很多类型的错误,一般情况下我们都是尽量调用Python的内置函数,也可以让自己编写的函数也可以抛出错误
用raise语句抛出一个错误的实例,raise语句如果不带参数,就会把当前错误原样抛出
class FooError(ValueError):
pass
def foo(s):
n = int(s)
if n==0:
raise FooError('invalid value: %s' % s)
return 10 / n
foo('0')
输出:
Traceback (most recent call last):
File "F:/pycharm/project/ten.py", line 36, in <module>
foo('0')
File "F:/pycharm/project/ten.py", line 33, in foo
raise FooError('invalid value: %s' % s)
__main__.FooError: invalid value: 0
2、调试
1、断言
凡是用print()来辅助查看的地方,都可以用断言(assert)来替代
在段言中,assert后面的语句应该成立,否则就输出最后面的错误提示
断言的开关“-O”是英文大写字母O,不是数字0
def foo(s):
n = int(s)
assert n != 0, 'n is zero!'
return 10 / n
def main():
foo('0')
输出:
Traceback (most recent call last):
...
AssertionError: n is zero!
2、logging
和assert比,logging不会抛出错误,而且可以输出到文件
- logging的好处,允许你指定记录信息的级别,指定level=INFO时,logging.debug就不起作用,指定level=WARNING后,debug和info就不起作用
- 日志等级从低到高的顺序是: DEBUG < INFO < WARNING < ERROR < CRITICAL
- DEBUG:程序调试bug时使用
- INFO:程序正常运行时使用
- WARNING:程序未按预期运行时使用,但并不是错误,如:用户登录密码错误
- ERROR:程序出错误时使用,如:IO操作失败
- CRITICAL:特别严重的问题,导致程序不能再继续运行时使用,如:磁盘空间为空,一般很少使 用
import logging
logging.basicConfig(level=logging.INFO)
s = '0'
n = int(s)
logging.info('n = %d' % n)
print(10 / n)
输出:
INFO:root:n = 0
Traceback (most recent call last):
File "F:/pycharm/project/ten.py", line 33, in <module>
print(10 / n)
ZeroDivisionError: division by zero