1. 错误,调试和测试
1.1 错误处理
try…except…finally…
- 如果有finally语句,不管是否捕获异常,finally语句一定会被执行。
- 在except后加else,当没有错误发生时,会自动执行else语句。
- Python的错误也是class,在使用except的时候注意,它不但捕获该类型的错误,还捕获其子类的错误。
调用堆栈
如果错误一直没有被捕获,它就会一直往上抛,最后被Python解释器捕获,打印一个错误消息,然后程序退出。# err.py:
def foo(s):
return 10 / int(s)
def bar(s):
return foo(s) * 2
def main():
bar('0')
main()
记录错误
既然我们能捕获异常,就可以把错误堆栈打印出来,然后分析错误原因,同时,让程序继续执行下去。 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')
通过配置,logging还可以把错误记录到日志文件里。
抛出错误 因为错误是class,捕获一个错误就是捕获该class的一个实例。因此,错误不是凭空产生的,而是有意创建并抛出的。# err_raise.py
class FooError(ValueError):
pass
def foo(s):
n = int(s)
if n==0:
raise FooError('invalid value: %s' % s) # 如果要抛出错误,首先,根据需要,可以定义一个错误的class,选择好继承关系,然后用raise语句抛出一个错误的实例。
return 10 / n
foo('0')
1.2 调试
使用print()打印可能有问题的变量。
断言def foo(s):
n = int(s)
assert n != 0, 'n is zero!'
return 10 / n
# assert的意思是表达式n!=0应该是True,否则,根据程序运行的逻辑,后面的代码肯定会出错
def main():
foo('0')
---
$ python3 err.py
Traceback (most recent call last):
...
AssertionError: n is zero!
Logging:和assert相比,logging不会抛出错误,而且可以输出到文件。
import logging
logging.basicConfig(level=logging.INFO) # 指定记录信息的级别
s = '0'
n = int(s)
logging.info('n = %d' % n) # logging.info()可以输出一段文本
print(10 / n)
pdb:启动Python解释器的调试器pdb,让程序以单步方式运行,可以随时查看运行状态。
pdb.set_trace:只需要import pdb,然后在可能出错的地方设置pdb.set_trace(),就可以设置一个断点。# err.py
import pdb
s = '0'
n = int(s)
pdb.set_trace() # 运行到这里会自动暂停,用命令p查看变量,命令c继续执行
print(10 / n)
IDE:PyCharm…
1.3 单元测试
单元测试是用来对一个模块,一个函数或者一个类来进行正确性检验的测试工作。
为了编写单元测试,需要引入Python自带的unittest模块。编写单元测试时,需要编写一个测试类,从unittest.TestCse继承。 以test开头的方法是测试方法,不以test开头的方法不被认为是测试方法,测试的时候不会被执行。self.assertEqual(abs(-1), 1) # 断言函数返回的结果与1相等
with self.assertRaises(KeyError):
value = d['empty']
setUp()和setDown()
可以在单元测试中编写两个特殊的setUp()和setDown()方法,这两个方法分别在每调用一个测试方法的前后分别被执行。1.4 文档测试
示例代码:很多文档都有示例代码,这些示例代码在Python的交互环境下输入并执行,结果与文档中的示例代码显示的一致。这些代码与其他说明可以写在注释中,然后,由一些工具来自动生成文档。
Python内置的文档测试(doctest)模块可以直接提取注释中的代码并执行测试。感谢提供的教程。系列都基于廖老师的教程。