错误、调试和测试——Python学习笔记09
来源:互联网 发布:淘宝用别人信用卡支付 编辑:程序博客网 时间:2024/06/06 05:55
错误处理
try
def foo(): #先定义两个函数 r = some_function() if r == (-1): return (-1) return rdef bar(): r = foo() if r == (-1): print('Error') else: pass
try的机制:
try: print('try…') r = 10 / 'a' print('result:', r)except ValueError as e: #错误类型有很多,如果有不同的类型错误,应该由不同的except语句块处理 print('ValueError:', e)except ZeroDivisionError as e: print('ZeroDivisionError:', e) #所有错误的类型都继承自BaseException,不但捕获该类型的错误,还把其子类一网打尽else: print('no Error!') #finally: print('finally…') #可以没有finally语句print('END')try还可以跨越多层调用:def foo(s): return 10 / int(s)def bar(s): return foo(s) * 2def main(): try: bar('0') except Exception as e: print('Error', e) finally: print('finally...')
调用堆栈
编写一个错误范例:
#err.pydef foo(s): return 10 / int(s)def bar(s): return foo(s) * 2def main(): bar('0')main()执行结果:Traceback (most recent call last): #tell us this is 错误的跟踪信息 File "err.py", line 11, in <module> #调用main()出错了,在第11行代码,但是真正的原因是在第9行 main() File "err.py", line 9, in main #调用的bar(‘0’)出错了,但是原因在第6行 bar('0') File "err.py", line 6, in bar #return foo(s) * 2这个语句出错了,但是原因在第3行 return foo(s) * 2 File "err.py", line 3, in foo #原来是return 10 / int(s)出错了,下方打印的是错误产生的源头 return 10 / int(s)ZeroDivisionError: division by zero #根据错误类型,我们判断int(s)本身没有出错,但是返回0,在计算10 / 0时出错
记录错误
logging可以记录错误,并且可以让程序打印完错误信息后继续运行:
#error_loggingimport logging #导入logging模块def foo(s): return 10 / int(s)def bar(s): return foo(s) * 2def main(): try: bar('0') except Exception as e: logging.except(e)main()print('END')
运行结果:
ERROR:root:division by zeroTraceback (most recent call last): #打印错误信息 File "/Users/Mojian/Desktop/learnpy/error_logging.py", line 12, in main bar('0') File "/Users/Mojian/Desktop/learnpy/error_logging.py", line 8, in bar return foo(s) * 2 File "/Users/Mojian/Desktop/learnpy/error_logging.py", line 5, in foo return 10 / int(s)ZeroDivisionError: division by zeroEND #程序继续运行,并正常退出
抛出错误
用raise语句跑出一个错误的实例:
class FooError(ValueError): passdef foo(s): n = int(s) if n == 0: raise FooError('invalid value: %s' % s) #尽量使用Python内置的错误类型,如ValueError等 return 10 / nfoo('0')
执行后,可以跟踪我们定义的错误:
Traceback (most recent call last): File "/Users/Mojian/Desktop/learnpy/error_raise.py", line 11, in <module> foo('0') File "/Users/Mojian/Desktop/learnpy/error_raise.py", line 8, in foo raise FooError('invalid value: %s' % s)FooError: invalid value: 0
还有另外一种错误处理方式:
def foo(s): n = int(s) if n == 0: raise ValueError('invalid value: %s' % s) return 10 / ndef bar(): try: foo('0') except ValueError as e: print('ValueError:', e) raise #raise如果不加参数,会把错误原样抛出bar()#返回:ValueError: invalid value: 0 File "<input>", line 13, in <module> File "<input>", line 9, in bar File "<input>", line 4, in fooValueError: invalid value: 0
运行过程:
1.bar()调用,函数开始执行,执行try—>foo('0') —>调用foo函数,参数’0’2.foo('0')开始执行,抛出错误raise ValueError('invalid value: %s' % 0)3.foo('0')此时抛出的错误不会在窗口中打印,抛到它的上级调用者----bar()中的try中4.try…except捕获到抛出的错误,except对错误类型进行对比—>找到此类型的错误处理信息—>错误进行处理—>错误再次抛出—>抛出到上级5.上级无try...except捕获并处理错误的语句,错误信息在窗口中打印出来
在except中raise一个Error,还可以把一种类型的错误转化成另一种,但,决不能把一个IOError 转换成 不相干的ValueError
try: 10 / 0except ZeroDivisionError as e: raise ValueError('input error!')
调试
print
调试第一种方法是直接打印出来调试信息:
def foo(s): n = int(s) print('>>> n = %s' % n) return 10 / ndef main(): foo('0')main()
执行后在输出中查找打印的变量值:
>>> n = 0Traceback (most recent call last): File "/Users/Mojian/Documents/调试1.py", line 9, in <module> main() File "/Users/Mojian/Documents/调试1.py", line 7, in main foo('0') File "/Users/Mojian/Documents/调试1.py", line 4, in foo return 10 / nZeroDivisionError: division by zero
坏处是还需删除print()
断言
def foo(s): n = int(s) assert n != 0, 'n is zero!'#判断n 是否为0,为0,抛出AssertionError return 10 / n #assert为Ture,则 继续进行def main(): #调用foo() foo('0')
logging
import logginglogging.basicConfig(level = logging.INFO)#指定记录信息的级别(debug,info,warning,error等),当指定level=warning时,logging.debug,info就不起作用s = '0'n = int(s)logging.info('n is %d' %n)print(10 / n)
单元测试
编写一个Dict类,这个类的行为和dict一致,但是可以通过属性访问,mydict.py:
class Dict(dict): def __init__(self, **kw): #__init__是构造函数(附带任何可选参数) super().__init__(**kw) #super继承父类,调用父类的__init__() def __getattr__(self, key): #__getattr__获得属性(getattr()内置方法) try: return self[key] except KeyError: raise AttributeError(r"'Dict has no attribute '%s'' % key) def __setattr__(self, key, value): self[key] = value #__setattr__设置属性;setattr赋给self对象的key属性 值 value
编写mydict_test:
import unittest#需引入Python自带的unitest模块from mydict import Dictclass TestDict(unitest.TestCase):#编写一个单元测试,需编写一个测试类,需从unittest.TestCase继承 def setUp(self):#可以在单元test中增加两个特殊方法,这两方法会分别在每调用一个测试方法的前后分别被执行 print('setUp…') def tearDown(self):#可以在setUp()中连接数据库,在tearDown中关闭数据库,不必在每个测试中重复代码 print('tearDown…') def test_init(self): #以test开头的方法是测试方法,才会在单元测试中被测试 d = Dict(a = 1, b = 'test') self.assertEqual(d.a, 1) self.assertEqual(d.b, 'test') self.assertTrue(isinstance(d, dict)) def test_key(self): d = Dict() d['key'] = 'value' self.assertEqual(d.key, 'value’)#最常用的断言assertEqual(),断言两个值相等 def test_attr(self): d = Dict() d.key = 'value' self.assertTrue('key' in d) #断言d中含有'key'属性 self.assertEqual(d['key'], value) def test_keyerror(self): d = Dict() with self.assertRaises(Keyerror):#另一种断言,期待抛出指定类型的Error value = d['empty’] def test_attrerror(self): d = Dict() with self.assertRaises(AttributeError):#如果value=d.empty,抛出的错误为AttributeError,则断言成功 value = d.empty if __name__ == '__main__': unittest.main() #所有的模块都有一个内置属性 __name__#当我们在命令行运行该模块文件时,Python解释器把一个特殊变量__name__置为__main__,而如果在其他地方导入该模块时,if判断将失败,因此,这种if测试可以让一个模块通过命令行运行时执行一些额外的代码,最常见的就是运行测试。
文档测试
# -*- coding: utf-8 -*-def fact(n): ''' >>> fact(3) 6 >>> fact(1) 1 >>> fact(0) Traceback(most recent call last): … #"…"表示中间烦人的输出 ValueError ''' if n < 1: raise ValueError if n == 1: return 1 return n * fact(n - 1)if __name__ == '__main__' import doctest #Python内置的doctest模块可以直接提取注释中的代码并执行测试 doctest.testmod() #运行后什么输出也没有#如果出现错误,程序就会报错,如:**********************************************************************File "mydict3.py", line 9, in __main__.factFailed example: fact(0)Exception raised: Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/doctest.py", line 1321, in __run compileflags, 1), test.globs) File "<doctest __main__.fact[2]>", line 1, in <module> fact(0) File "mydict3.py", line 15, in fact raise ValueError ValueError**********************************************************************1 items had failures: #表示测试执行失败数,无失败时无输出 1 of 3 in __main__.fact***Test Failed*** 1 failures.
阅读全文
0 0
- 【Python】学习笔记——-09、错误、调试和测试
- 错误、调试和测试——Python学习笔记09
- Python错误、调试和测试——学习笔记
- 【Python学习笔记】错误、调试和测试
- Python学习笔记(八)——错误、调试、测试
- python学习(14)——错误,调试和测试
- python学习笔记(1)-错误处理、调试和测试
- Python学习笔记(六)错误、调试和测试
- Python学习笔记10_错误、调试和测试
- python学习笔记(八) - 错误、调试、测试
- Python学习----错误、调试和测试
- 学习笔记_错误、调试和测试
- Python学习笔记(八):面向对象编程、错误调试和测试(快速入门篇)
- python错误、调试和测试
- python错误调试和测试
- Python错误、调试和测试
- Python学习 (七 错误、调试和测试)
- Python学习5--类、错误、调试、测试
- kNN和MDS降维
- jQuery中的DOM操作
- UnityShader——挺进体积光
- ShiroFilterFactoryBean过滤器数量限制问题
- poj1159(dp)
- 错误、调试和测试——Python学习笔记09
- 竖直ViewPager
- 函数练习
- 移动端适配
- 51nod 1686-第K大区间(离散化+二分+尺取)
- X的平方根
- Ubuntu 16.04.1安装MySQL
- CSU-ACM2017暑假集训比赛7
- 关于springboot+websocket+mybatis的问题