Python学习笔记(六)
Python错误与异常处理
错误处理
在Python中提供了错误处理机制try...except...
:
try:
a = 10
b = 0
print("a/b =%d" % (a/b))
except Exception:
print("catch exception")
运行结果:
catch exception
在执行try
代码块时如果出现异常情况,try
代码块中的代码将会被终止而执行except
代码块的内容。当代码可能可能跑出多个异常的时候,可以用多个except
块来处理:
try:
print(abs("s"))
except TypeError :
print("catch TypeError")
except ValueError:
print("catch ValueError")
运行结果:
catch TypeError
如果没有错误发生,可以在except
语句块后面加一个else
,当没有错误发生时,会自动执行else
语句:
try:
a = 10
b = 1
print("a/b =%d" % (a/b))
except Exception :
print("catch exception")
else:
print("END")
运行结果:
a/b =10
END
在程序发生异常时,有时候需要清理释放一些系统资源,需要用到finally
语句,finally
语句是不论有没有异常发生,里面的代码都会被执行:
try:
print(abs("s"))
except TypeError :
print("catch TypeError")
except ValueError:
print("catch ValueError")
else:
print("END")
finally:
print("fianlly")
运行结果:
catch TypeError
fianlly
raise
语句用来抛出异常,当异常在当前函数中处理不了时可以将异常抛给上层调用者去处理:
try:
10 / 0
except ZeroDivisionError:
raise ValueError('input error!')
运行结果:
Traceback (most recent call last):
File "C:/Users/chenlixiong/PycharmProjects/untitled/hello.py", line 2, in <module>
10 / 0
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:/Users/chenlixiong/PycharmProjects/untitled/hello.py", line 4, in <module>
raise ValueError('input error!')
ValueError: input error!
调试
调试的几种方式:
- 用
print()
将可能出问题的变量打印出来,用起来不是很方便,尤其是代码有大量的print()
语句时。 断言。如果
assert
里面的表达式为True,断言成功,否则断言失败。如果断言失败,assert语句本身就会抛出AssertionError:def f(n): n =int(n) assert n!=0 ,"n is zero" return 10/n print(f(0)) 运行结果: Traceback (most recent call last): ... AssertionError: n is zero
打log。
logging
不会抛出错误,而且可以输出到文件。它允许你指定记录信息的级别,有debug
,info
,warning
,error
等几个级别,可以放心地输出不同级别的信息,也不用删除,最后统一控制输出哪个级别的信息。import logging logging.basicConfig(level=logging.INFO) def f(n): n =int(n) logging.info("n = %d" % n) return 10/n print(f(0)) 运行结果: INFO:root:n = 0 Traceback (most recent call last): ... ZeroDivisionError: division by zero
通过IDE工具打断点对程序进行调试。
单元测试
单元测试是用来对一个模块、一个函数或者一个类来进行正确性检验的测试工作。以测试一个方法为例:
def add(a,b):
return a+b
def sub(a,b):
return a-b
测试模块:
import unittest
import mytest
class Test(unittest.TestCase):
def test_add(self):
self.assertEquals(mytest.add(2,8),10)
def test_sub(self):
self.assertEquals(mytest.sub(5,2),3)
def setUp(self):
print('setUp...')
def tearDown(self):
print('tearDown...')
if __name__ == '__main__':
unittest.main()
因此编写测试代码必须引入Python自带的unittest
模块,编写一个继承自unittest.TestCase
的测试类。以test
开头的方法就是测试方法,不以test
开头的方法不被认为是测试方法,测试的时候不会被执行。用assertEqual()
断言来测试结果是否与期望一致。
if __name__ == '__main__':
unittest.main()
在测试模板的最后加两行以上代码,就可以将测试脚本当作正常的的python脚本来运行。
setUp()
和tearDown()
这两个方法会分别在每调用一个测试方法的前后分别被执行。
参考资料:廖雪峰的官方网址