【Python3 笔记】Python3 错误处理 调试 单元测试 文档测试

本系列是学习 廖雪峰 Python3 教程 过程中记录的笔记,本篇文章记录 Python 常用的错误处理、调试,以及单元测试和文档测试的一般做法。

错误处理

try...finally

  • 将可能出错的代码放在 try 语句块中,出错抛出的异常会被 except 捕获,执行 except 语句块的内容,如果有 finally ,则不论是否发生异常,都会执行其语句块中的内容;

  • except 可以捕获多种异常,异常也是class,全部都继承自BaseException,其中父类也可以捕获子类的异常;

  • 常见的错误类型和继承关系 看这里

  • 多个层级调用中,内层中的异常可以被外层设置的 except 捕获,即异常的跨层调用;

    try:
        print('try...')
        r = 10 / 0
        print('result:', r)
    except ZeroDivisionError as e:
        print('except:', e)
    finally:
        print('finally...')
    print('END')
    
    output—————————————————
    except: division by zero
    finally...
    END
    

logging

  • 调用栈(异常栈):就是程序报错时那一行行红色的信息,可以顺次定位到出错的位置;

  • 配合 logging 可记录错误信息,打印后程序会继续执行,也可以配置 logging 将错误信息输出到文件,便于后续分析和查看;

    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')
    
    output————————————————
    ERROR:root:division by zero
    Traceback (most recent call last):
      File "F:/wtlGit/python3_notes/note_06.py", line 26, in main
        bar('0')
      File "F:/wtlGit/python3_notes/note_06.py", line 22, in bar
        return foo(s) * 2
      File "F:/wtlGit/python3_notes/note_06.py", line 19, in foo
        return 10 / int(s)
    ZeroDivisionError: division by zero
    END
    

调试

  • print() 将需要查看的内容直接打印出来,最常用;

  • 断言:assert n != 0, 'n is zero!' 表达式为真时继续执行,为假时输出后续信息;

  • 在启动 Python 编译器时,可以通过 -O 来关闭 assert,关闭后相当于 pass

    python -O err.py
    
  • IDE 调试,常用的就是 Visual Studio Code PyCharm,可以设置断点、单步执行等;

单元测试

  • 测试用例要覆盖常用的输入组合、边界条件和异常;

  • 代码要非常简单,如果测试代码太复杂,那么测试代码本身就可能有bug;

  • 使用unittest 编写测试方法,可以进行批量测试;

    import unittest
    
    class Student(object):
        def __init__(self, name, score):
            self.name = name
            self.score = score
            self.grade = 'None'
    
        def get_grade(self):
            if self.score < 0 or self.score > 100:
                raise ValueError("the score out of range, should be in [0, 100]")
    
            if self.score >= 80:
                self.grade = 'A'
            elif self.score >= 60:
                self.grade = 'B'
            else:
                self.grade = 'C'
            return self.grade
    
    
    class TestStudent(unittest.TestCase):
    
        def test_80_to_100(self):
            s1 = Student('Bart', 80)
            s2 = Student('Lisa', 100)
            self.assertEqual(s1.get_grade(), 'A')
            self.assertEqual(s2.get_grade(), 'A')
    
        def test_60_to_80(self):
            s1 = Student('Bart', 60)
            s2 = Student('Lisa', 79)
            self.assertEqual(s1.get_grade(), 'B')
            self.assertEqual(s2.get_grade(), 'B')
    
        def test_0_to_60(self):
            s1 = Student('Bart', 0)
            s2 = Student('Lisa', 59)
            self.assertEqual(s1.get_grade(), 'C')
            self.assertEqual(s2.get_grade(), 'C')
    
        def test_invalid(self):
            s1 = Student('Bart', -1)
            s2 = Student('Lisa', 101)
            with self.assertRaises(ValueError):
                s1.get_grade()
            with self.assertRaises(ValueError):
                s2.get_grade()
    
    
    if __name__ == '__main__':
        unittest.main()
    
    output——————————————————
    ....
    ----------------------------------------------------------------------
    Ran 4 tests in 0.000s
    
    OK
    

文档测试

  • 使用 doctest 进行文档测试,会将函数中开头的注释部分提取出来自动执行,如果注释部分没问题,那么测试执行后不会有任何输出;

    def fact(n):
        '''
        Calculate 1*2*...*n
        >>> fact(1)
        1
        >>> fact(10)
        3628800
        >>> fact(-1)
        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
        doctest.testmod()
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值