Python3异常处理与调试(v3.7)

[TOC]

异常处理

Python异常处理采用 try...except...finally 语法,其中finally可以省略。

Python所有错误其实是class,所有错误类型都继承自BaseException
常见错误类型

1
2
3
4
5
6
7
8
9
try :
print('代码开始')
n = 10 / 0
print('结果:%s' % n)
except ZeroDivisionError as ze :
print(ze)
finally :
print('代码结束')
print('END')

当try中代码出现错误时被except捕获,try中后续代码中止执行,继续执行except中代码,最后执行finally中代码,无论except是否捕获错误finally都会执行。except后还可加else条件:

1
2
3
4
5
6
7
8
9
10
try :
...
except ... :
...
except ... :
...
else :
#未捕获到异常执行此处代码
finally :
#最后执行的代码

代码中通过try...except...finally捕获异常后其后续代码可以继续运行,如前面代码最终打印出“END”,如果没有捕获异常此处打印“END”将不会被执行,程序将退出终止执行。

错误记录

Python内置logging模块可以用来记录错误信息,并可通过配置记录成本地文件。

1
2
3
4
5
6
import logging #导入模块

try :
...
except Exception as e :
logging.exception(e)

错误抛出

抛出错误通过关键字raise实现。

1
2
3
4
5
6
7
def func(param) : #默认参数为5
if not isinstance(param,(int,float)) :
raise TypeError('invalid param') #抛出异常
if param < 10 :
return param;
else :
return 10;

调试

程序调试一种方法是可以通过print()打印,但它的缺点是将来须要将其删除;而另一种方法就是断言(assert)。

1
2
3
4
5
6
def foot(n) :
n = int(n)
assert n < 10 ,'n too large!'
return 10 - n

>>> foot(20)

assert语法为assert 表达式,'断言内容',表达式中为True则断言成功,否则断言失败抛出AssertionError异常和断言内容,程序中止执行。可以通过启动增加-o参数关闭断言。

1
python -o app.py

第三种调试方法就是logging(日志),它可以输出到文件,并且可以设置DEBUGINFOWARNINGERROR等几个级别。

1
2
3
4
import logging
logging.basicConfig(level=logging.INFO)

logging.info('') #INFO级别日志

第四种是启动Python调试器pdb,让程序以单步方式运行,可以随时查看程序运行状态。

1
python -m pdb app.py

-m pdb参数启动Python后,pdb将定位到下一步要执行的代码,输入l命令查看代码,输入n单步查看代码,可以输入p 变量名查看变量,输入q退出程序

也可以在代码中嵌入pdb.set_trace(),程序会在此处暂时进入pdb调试环境,可以使用p 变量名查看变量或者使用c命令继续运行。

1
2
3
4
5
import pdb #嵌入pdb需要引入pdb模块

代码...
pdb.set_trace() # 运行到这里会自动暂停
代码...

测试

单元测试

Python单元测试需要引入unittest模块,测试类需要继承unittest.TestCase,并且测试方法需要以test开头,否则不被认为是单元测试,测试方法一般通过断言进行测试。

1
2
3
4
5
6
7
8
9
10
11
import unittest

class TestDict(unittest.TestCase) :
def test_init(self) :
d = Dict(a=1, b='test')
self.assertEqual(d.a, 1)
self.assertTrue(isinstance(d, dict))
...省略

if __name__ == '__main__' :
unittest.main() # 执行脚本运行单元测试

文档测试

Python内置文档测试doctest模块可以直接提取注释中代码并执行测试。doctest严格按照Python交互式命令行的输入和输出来判断测试结果是否正确。只有测试异常的时候,才会有输出错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Dict(dict) :
'''
...说明内容

>>> d1 = Dict()
>>> d1['x'] = 100
>>> d1.x

...省略
'''

代码实现...

if __name__=='__main__':
import doctest
doctest.testmod()

上面代码是文档测试的样例,注意>>>后面代码,当执行文档测试时,该代码会被执行验证,同时此代码也可当作示例代码。