(Python Primary) - 廖雪峰Python3 - 10.错误、调试和测试

10.错误、调试和测试

10.1错误处理

  • try...catch机制
try:
    print('try...')
    r = 10 / 0
    print('result:', r)
except ZeroDivisionError as e:
    print('except:', e)
else:
    print('no error!')		#如果没有错误发生
finally:
    print('finally...')
print('END')
  • 所有的错误类型都继承自BaseException

  • 调用栈:如果错误没有被捕获,它就会一直往上抛,最后被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')
  • 抛出错误raise(如果不带参数就抛出原错误,还可以把一个错误转为另一种类型)
def foo(s):
    n = int(s)
    if n==0:
        raise ValueError('invalid value: %s' % s)
    return 10 / n

def bar():
    try:
        foo('0')
    except ValueError as e:
        print('ValueError!')
        raise

bar()

10.2调试

  • print()调试
  • assert()(可以用python -O err.py关闭)
def foo(s):
    n = int(s)
    assert n != 0, 'n is zero!'	# 若条件不满足,就抛出AssertionError错误
    return 10 / n

def main():
    foo('0')
  • logging,不会抛出错误,可以输出到文件,允许你指定记录信息的级别,有debuginfowarningerror等几个级别
import logging
logging.basicConfig(level=logging.INFO)
  • pdb,Python的调试器,让程序以单步运行,随时查看运行状态
$ python -m pdb err.py
> /Users/michael/Github/learn-python3/samples/debug/err.py(2)<module>()
-> s = '0'
(Pdb) l
  1     # err.py
  2  -> s = '0'
  3     n = int(s)
  4     print(10 / n)
(Pdb) n
> /Users/michael/Github/learn-python3/samples/debug/err.py(3)<module>()
-> n = int(s)
(Pdb) n
> /Users/michael/Github/learn-python3/samples/debug/err.py(4)<module>()
-> print(10 / n)
(Pdb) p s	# 输入命令p 变量名来查看变量
'0'
(Pdb) p n	# 输入命令q结束调试,退出程序
0
(Pdb) q
  • pdb.set_trace(),只需要import pdb,在可能出错的地方放一个pdb.set_trace()
  • IDE

10.3单元测试(unit_test)

  • 编写需要测试的类
class Dict(dict):

    def __init__(self, **kw):
        super().__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
  • 编写测试类,测试函数必须以test_xxx()开头
import unittest

from mydict import Dict
	
class TestDict(unittest.TestCase):		# 测试类,从unittest.TestCase继承

    def test_init(self):
        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')

    def test_attr(self):
        d = Dict()
        d.key = 'value'
        self.assertTrue('key' in d)
        self.assertEqual(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
  • 常用的断言

    • assertEqual()

      self.assertEqual(abs(-1), 1) # 断言函数返回的结果与1相等
      
    • assertRaises()

      with self.assertRaises(KeyError):
          value = d['empty']
      
  • 运行单元测试

if __name__ == '__main__':
    unittest.main()
# or
python mydict_test.py
# or
python -m unittest mydict_test
  • setUp与tearDown,这两个方法会分别在每调用一个测试方法的前后分别被执行

10.4文档测试doctest

  • Python内置的“文档测试”(doctest)模块可以直接提取注释中的代码并执行测试

  • e.g.

# mydict2.py
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()
  • 比如把__getattr__()方法注释掉,再运行就会报错
$ python mydict2.py
**********************************************************************
File "/Users/michael/Github/learn-python3/samples/debug/mydict2.py", line 10, in __main__.Dict
Failed example:
    d1.x
Exception raised:
    Traceback (most recent call last):
      ...
    AttributeError: 'Dict' object has no attribute 'x'
**********************************************************************
File "/Users/michael/Github/learn-python3/samples/debug/mydict2.py", line 16, in __main__.Dict
Failed example:
    d2.c
Exception raised:
    Traceback (most recent call last):
      ...
    AttributeError: 'Dict' object has no attribute 'c'
**********************************************************************
1 items had failures:
   2 of   9 in __main__.Dict
***Test Failed*** 2 failures.

参考教程

廖雪峰老师的Python3教程

(转载整理自网络,如有侵权,联系本人删除,仅供技术总结使用)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值