1.错误处理
#!/usr/bin/env python # -*- coding: utf-8 -*- import logging #定义一个自定义错误,继承自StandardError class FooError(StandardError): pass def func1(value): return 10/int(value) def func2(value): #使用try-except-else捕获异常,打印异常日志,并且使用raise抛出一个FooError异常 try: return func1(value) except ZeroDivisionError,e: logging.exception(e) raise FooError('invalid value: %s' % value) else: print 'func2 success' def func3(value): #使用try-except-else-finally捕获并处理异常 try: print '----START----' return func2(value) except FooError,e: print 'catch a fooerror' else: print 'func3 success' finally: print '----END----'
func3(0) ```
2.调试
1.print
2.断言assert
如果断言失败,assert语句本身就会抛出AssertionError:
assert的意思是,表达式n != 0应该是True,否则,后面的代码就会出错。# err.py def foo(s): n = int(s) assert n != 0, 'n is zero!' return 10 / n def main(): foo('0')
启动Python解释器时可以用-O参数来关闭assert
$ python -O err.py
关闭后,你可以把所有的assert语句当成pass来看
3.logging
logging允许你指定记录信息的级别,有debug,info,warning,error等几个级别,当我们指定level=INFO时,logging.debug就不起作用了
logging的另一个好处是通过简单的配置,一条语句可以同时输出到不同的地方,比如console和文件#!/usr/bin/env python # -*- coding: utf-8 -*- import logging #设置logging的显示级别 logging.basicConfig(level=logging.INFO) s = '0' n = int(s) logging.info('n = %d' % n) print 10 / n
4.pdb单步调试
启动pdb单步调试
$ python -m pdb err.py
命令l可以查看代码
命令n可以单步执行代码
命令p 变量名可以查看变量
命令q可以结束调试,退出程序5.pdb.set_trace()设置断点
在可能出错的地方放一个pdb.set_trace(),就可以设置一个断点
# err.py import pdb s = '0' n = int(s) pdb.set_trace() # 运行到这里会自动暂停 print 10 / n
程序会自动在pdb.set_trace()暂停并进入pdb调试环境,可以用命令p查看变量,或者用命令c继续运行
3.单元测试
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
mydict_test.py
import unittest from mydict import Dict class 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): 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): d = Dict() with self.assertRaises(KeyError): value = d['empty'] def test_attrerror(self): d = Dict() with self.assertRaises(AttributeError): value = d.empty if __name__ == '__main__': unittest.main()
运行单元测试
方法一:$ python mydict_test.py
方法二:
$ python -m unittest mydict_test
setUp与tearDown
这两个方法会分别在每调用一个测试方法的前后分别被执行
比如,可以在setUp()方法中连接数据库,在tearDown()方法中关闭数据库
4.文档测试
Python内置的“文档测试”(doctest)模块可以直接提取注释中的代码并执行测试
class Dict(dict): ''' Simple dict but also support access as x.y style. >>> d1 = Dict() >>> d1['x'] = 100 >>> d1.x 100 >>> 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.empty Traceback (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] = value if __name__=='__main__': import doctest doctest.testmod()
注意到最后两行代码。当模块正常导入时,doctest不会被执行。只有在命令行运行时,才执行doctest。所以,不必担心doctest会在非测试环境下执行。