Day-10: 错误、调试和测试
程序运行时,会遇到各种各样的错误。
编写错误叫做bug,而另一类由于运行过程中无法预测的,比如写文件时,磁盘满了,写不进去;或者从网络抓取数据,网络突然掉了。这些错误称为异常,程序中需要对异常进行处理,使得程序能够运行下去。
- 错误处理
Python中,程序运行错误时,如果错误没有捕获,它会一直往上抛,最后被Python解释器捕获,打印一个错误。
# err.py: def foo(s):return 10 / int(s)def bar(s):return foo(s) * 2def main():bar('0')main()
$ python err.py Traceback (most recent call last):File "err.py", line 11, in <module>main()File "err.py", line 9, in mainbar('0')File "err.py", line 6, in barreturn foo(s) * 2File "err.py", line 3, in fooreturn 10 / int(s) ZeroDivisionError: integer division or modulo by zero
从上到下,错误会一层层的反馈,直到显示最终出错的地方。
try...except...finally...:常用这种方法来检查错误并捕捉到,同时进行相应的处理。
try:print 'try...'r = 10 / 0print 'result:', r except ZeroDivisionError, e:print 'except:', e finally:print 'finally...' print 'END'
try... except: integer division or modulo by zero finally... END
注意到,错误类型有很多种,它们其实都是从BaseException类派生出来的,常见的错误类型和继承关系有:https://docs.python.org/2/library/exceptions.html#exception-hierarchy
- 调试
程序运行一次就成功的概率很小,基本上不超过1%。一般有如下的调试方法:
第一种,直接在可能出错的地方print出来,但是后期会一个个删掉。
第二种,使用断言来代替。
# err.py def foo(s):n = int(s)assert n != 0, 'n is zero!'return 10 / ndef main():foo('0')
断言中,如果“n != 0”是错的,就抛出AssertionError,并显示后面的字符串。
第三种,使用logging。
logging有debug,info,warning,error等几个级别,从前到后优先级依次提高,即如果,指定level=WARNING后,debug和info就不起作用了。这样一样,就可以输出不同级别的信息,也不用删除,最后统一控制输出哪个级别的信息。
logging的另一个好处是通过简单的配置,一条语句可以同时输出到不同的地方,,比如console和文件。
# err.py import logginglogging.basicConfig(level=logging.INFO)s = '0' n = int(s) logging.info('n = %d' % n) print 10 / n
$ python err.py INFO:root:n = 0 Traceback (most recent call last):File "err.py", line 8, in <module>print 10 / n ZeroDivisionError: integer division or modulo by zero
第四种调试方式,就是调试器pdb,让程序以单步方式运行,可以随时查看运行状态。
# err.py s = '0' n = int(s) print 10 / n
然后,以参数-m pdb启动,单步运行
$ python -m pdb err.py > /Users/michael/Github/sicp/err.py(2)<module>() -> s = '0'
(Pdb) l1 # err.py2 -> s = '0'3 n = int(s)4 print 10 / n [EOF]
输入n单步运行下一步
(Pdb) n > /Users/michael/Github/sicp/err.py(3)<module>() -> n = int(s) (Pdb) n > /Users/michael/Github/sicp/err.py(4)<module>() -> print 10 / n
输入p 变量名来查看变量状态。
(Pdb) p s '0' (Pdb) p n 0
输入q结束运行
(Pdb) n ZeroDivisionError: 'integer division or modulo by zero' > /Users/michael/Github/sicp/err.py(4)<module>() -> print 10 / n (Pdb) q
另外在合适的地方,设置pdb.set_trace(),可以作为断点。
# err.py import pdbs = '0' n = int(s) pdb.set_trace() # 运行到这里会自动暂停 print 10 / n
$ python err.py > /Users/michael/Github/sicp/err.py(7)<module>() -> print 10 / n (Pdb) p n 0 (Pdb) c Traceback (most recent call last):File "err.py", line 7, in <module>print 10 / n ZeroDivisionError: integer division or modulo by zero
到达断点时,进入pdb调试器。
最后,还有方便的IDE调试器。
- 单元测试
单元测试,顾名思义,就是对一个部分测试,可以是一个模块、一个函数或者一个类。它的目的是保证该单元能够实现原先规划的功能,为之后的整体调试做准备。
例如,现有模块mydict.py,对它的要求是实现如下功能:
>>> d = Dict(a=1, b=2) >>> d['a'] 1 >>> d.a 1
mydict.py代码如下:
class Dict(dict):def __init__(self, **kw):super(Dict, self).__init__(**kw)def __getattr__(self, key):try:return self[key]except KeyError:raise AttributeError(r"'Dict' object has no attribute '%s'" % key)def __setattr__(self, key, value):self[key] = value
编写的单元测试,需要引入unittest模块,编写的mydict_test.py如下:
import unittestfrom mydict import Dictclass TestDict(unittest.TestCase):def test_init(self): # 测试初始化功能d = Dict(a=1, b='test')self.assertEquals(d.a, 1)self.assertEquals(d.b, 'test')self.assertTrue(isinstance(d, dict))def test_key(self): # 测试key的功能d = Dict()d['key'] = 'value'self.assertEquals(d.key, 'value')def test_attr(self): # 测试属性功能d = Dict()d.key = 'value'self.assertTrue('key' in d)self.assertEquals(d['key'], 'value')def test_keyerror(self): # 测试key错误的功能d = Dict()with self.assertRaises(KeyError):value = d['empty']def test_attrerror(self): # 测试属性错误的功能d = Dict()with self.assertRaises(AttributeError):value = d.empty
编写的单元测试类,从unittest.TestCase继承。其中,只有以test开头的方法是测试方法。
运行单元测试时,可以在测试文件中加入:
if __name__ == '__main__':unittest.main()
然后run。
另一种,在命令行中输入命令:
$ python -m unittest mydict_test ..... ---------------------------------------------------------------------- Ran 5 tests in 0.000sOK
第二种方法,可以一次运行多个测试文件,比较方便。
setUp与tearDown:在每个测试方法前后分别被执行,避免在测试代码中重复加入代码。
最后,单元测试要考虑到异常,代码不能过于复杂,以免本身就有bug。
- 文档测试
Python中可以提供实例文档,在文件中编写特定格式的注释,调用doctest判断程序是否会像注释中那样的运行。
class Dict(dict):'''Simple dict but also support access as x.y style.>>> d1 = Dict()>>> d1['x'] = 100>>> d1.x100>>> d1.y = 200>>> d1['y']200>>> d2 = Dict(a=1, b=2, c='3')>>> d2.c'3'>>> d2['empty']Traceback (most recent call last):...KeyError: 'empty'>>> d2.emptyTraceback (most recent call last):...AttributeError: 'Dict' object has no attribute 'empty''''def __init__(self, **kw):super(Dict, self).__init__(**kw)def __getattr__(self, key):try:return self[key]except KeyError:raise AttributeError(r"'Dict' object has no attribute '%s'" % key)def __setattr__(self, key, value):self[key] = valueif __name__=='__main__':import doctestdoctest.testmod()
然后run。如果什么都没输出,就说明编写的doctest运行都是正确的。
注:本文为学习廖雪峰Python入门整理后的笔记
转载于:https://www.cnblogs.com/likely-kan/p/7517924.html
Day-10: 错误、调试和测试相关推荐
- error 系统错误 错误码10007_Python学习之错误调试和测试
Python学习之错误调试和测试 Python学习目录 在Mac下使用Python3 Python学习之数据类型 Python学习之函数 Python学习之高级特性 Python学习之函数式编程 Py ...
- cfree运行程序错误的原因_Python入门教程 | 第 8 章 错误、调试和测试
第八章 错误.调试和测试 在程序运行过程中,总会遇到各种各样的错误. 有的错误是程序编写有问题造成的,比如本来应该输出整数结果输出了字符串,这种错误我们通常称之为bug,bug是必须修复的. 有的错误 ...
- 硬件测试含软件调试,硬件调试与测试规范.doc
第 PAGE i页 硬件调试与测试规范 目录 TOC \o "1-3" \h \z 前言 3 1参考标准 3 2适用范围 3 3硬件调试与测试规范 3 3.1硬件测试流程细则 3 ...
- Nginx 附录C 模块编译,调试与测试
Nginx 附录C 模块编译,调试与测试 C.1 编译与安装 环境要求 操作系统:目前Nginx各版本在以下操作系统和平台测试通过: FreeBSD 3 - 10 / i386; FreeBSD 5 ...
- WEB十大安全漏洞(OWASP Top 10)与渗透测试记录
1. 前言 每年 OWASP(开放 Web 应用程序安全项目)都会发布十大安全漏洞.它代表了对 Web 应用程序最关键的安全风险的广泛共识.了解十大WEB漏洞种类并善于在渗透测试中发现漏洞是安全行业人 ...
- 几种Linux段错误调试方法
一.产生段错误的原因 段错误就是指某一进程访问了不属于它权限范围的内存空间,比如:访问了不存在的内存,访问了受系统保护的内存,访问了只读的内存等.下面是一段会产生段错误的实例代码:main.c #in ...
- git.exe init#timeout = 10错误:克隆远程repo'origin'时出错hudson.plugins.git
用Jenkins自动化搭建测试环境,Jenkins构建任务 关键异常抓取 git.exe init#timeout = 10错误:克隆远程repo'origin'时出错hudson.plugins.g ...
- 并行程序调试、测试与模型检测
并行程序调试.测试与模型检测 并行程序调试的挑战: 1.由于不能确定不同线程的执行顺序,导致可能的执行路径发生组合爆炸: 2.使用模型检验程序正确性能以应用到分布式系统上. 名词解释 确定性重放:通过 ...
- 正确理解以下名词及其含义1源程序,目标程序,可执行程序2程序编辑,程序编译,程序连接3程序,程序模块,程序文件4函数,主函数,被调用函数,库函数5程序调试,程序测试
正确理解以下名词及其含义: (1)源程序,目标程序,可执行程序. 源程序:指未编译的按照一定的程序设计语言规范书写的文本文件,是一系列人类可读的计算机语言指令目标程序:为源程序经编译可直接被计算机运行 ...
- Java程序员应该知道的10个调试技巧
摘要:调试不仅可以查找到应用程序缺陷所在,还可以解决缺陷.对于Java程序员来说,他们不仅要学会如何在Eclipse里面开发像样的程序,更需要学会如何调试程序.本文介绍了Java程序员必知的10个调试 ...
最新文章
- 重构职场竞争力之测试能力提升方法
- Mac下安装JDK以及怎么配置环境变量?
- 计算机除法和取余在实际运用中的意义
- 查看Servlet 3.0的新增功能
- 函数的自执行,变量提升和函数提升
- 前端学习(1154):常量const02
- java关键字:volatile
- 利用Python制作一个“电子记事本”
- Git:查看所有远程分支以及同步远程代码
- 升级成员服务器-从Windows 2012升级到2016案例之2
- 请简述java的异常体系,Java的异常体系 面试题
- python创建子窗口_python GUI编程(Tkinter) 创建子窗口及在窗口上用图片绘图实例
- 服务封装软件 nssm
- Java之力[从蛮荒到撬动地球]之设计模式
- 码易手机站,现已轻快上线!
- 与10.110.12.30 mask 255.255.255.224属于同一网段的主机IP地址是?
- 排序算法大比拼(2.2)——时间O(n log2n)篇之快速排序(左右指针法)
- Android移动开发-Android开发日历时常用的农历和公历换算代码工具类
- C#做一个简单浏览器
- IDEA之翻译器的妙用Translation
热门文章
- java中exec命令,java - 从Java中运行exec命令需要 bash 吗? - SO中文参考 - www.soinside.com...
- 什么是 restful api
- 8皇后以及N皇后算法探究,回溯算法的JAVA实现,递归方案(一)
- 9适应之力加多少攻击_剑盾铠之孤岛DLC新增内容大全! 宝可梦史上第一款DLC到底香不香(含试玩视频)...
- Nginx开发一个简单的HTTP过滤模块
- 对于一个字符串,请设计一个高效算法,找到第一次重复出现的字符
- opencv之图象裁剪
- centos中的配置文件
- Scala入门到精通——第四节 Set、Map、Tuple、队列操作实战
- 处理 Maven 项目名称红色感叹号的问题