• Python 错误、调试和测试


    一、错误处理

    1. try 错误捕捉

    常见的错误类型和继承关系看这里:
    https://docs.python.org/3/library/exceptions.html#exception-hierarchy
    注意:使用except时需要注意的是,它不但捕获该类型的错误,还把其子类也“一网打尽”。

    try:
        print('try...')
        r = 10 / 0
        print('result:', r)
    except ZeroDivisionError as e:
        print('except:', e)
    finally:
        print('finally...')
    print('END')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    当我们认为某些代码可能会出错时,就可以用try来运行这段代码,如果执行出错,则后续代码不会继续执行,而是直接跳转至错误处理代码,即except语句块,执行完except后,如果有finally语句块,则执行finally语句块,至此,执行完毕。

    错误有很多种类,如果发生了不同类型的错误,应该由不同的except语句块处理.

    try:
        print('try...')
        r = 10 / int('2')
        print('result:', r)
    except ValueError as e:
        print('ValueError:', e)
    except ZeroDivisionError as e:
        print('ZeroDivisionError:', e)
    else:
        print('no error!')
    finally:
        print('finally...')
    print('END')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2. 记录错误

    使用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')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    3. 抛出错误

    使用raise语句抛出一个错误的实例

    # err_raise.py
    class FooError(ValueError):
        pass
    
    def foo(s):
        n = int(s)
        if n==0:
            raise FooError('invalid value: %s' % s)
        return 10 / n
    
    foo('0')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    二、调试

    1. print() 进行输出

    2. 断言

    print()来辅助查看的地方,都可以用断言(assert)来替代。
    启动Python解释器时可以用-O参数来关闭assert:$ python -O err.py

    def foo(s):
        n = int(s)
        assert n != 0, 'n is zero!'
        return 10 / n
    
    def main():
        foo('0')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3. logging

    print()替换为logging,和assert比,logging不会抛出错误,而且可以输出到文件.

    import logging
    logging.basicConfig(level=logging.INFO)
    
    s = '0'
    n = int(s)
    logging.info('n = %d' % n)
    print(10 / n)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    logging.info()就可以输出一段文本。允许你指定记录信息的级别,有debug,info,warning,error等几个级别.

    4. pdb

    启动Python的调试器pdb,让程序以单步方式运行,可以随时查看运行状态

    $ python -m pdb err.py
    
    • 1
    • 输入命令l来查看代码
    • 输入命令n可以单步执行代码
    • 输入命令q结束调试,退出程序

    5. IDE

    三、单元测试

    mydict.py代码如下:

    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  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    1. 编写单元测试
      编写单元测试时,
      引入Python自带的unittest模块,
      我们需要编写一个测试类,从unittest.TestCase继承。
      以test开头的方法就是测试方法,不以test开头的方法不被认为是测试方法,测试的时候不会被执行。
      编写mydict_test.py如下:
    import unittest
    
    from mydict import Dict
    
    class TestDict(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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    1. 运行单元测试
      最简单的运行方式是在mydict_test.py的最后加上两行代码
    if __name__ == '__main__':
        unittest.main()
    
    • 1
    • 2

    这样就可以把mydict_test.py当做正常的python脚本运行:

    $ python mydict_test.py
    
    • 1

    另一种方法是在命令行通过参数-m unittest直接运行单元测试:

    $ python -m unittest mydict_test
    
    • 1
    1. setUp与tearDown
      设想你的测试需要启动一个数据库,这时,就可以在setUp()方法中连接数据库,在tearDown()方法中关闭数据库,这样,不必在每个测试方法中重复相同的代码.

    四、文档测试

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

    # 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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    运行 $ python mydict2.py
    什么输出也没有。这说明我们编写的doctest运行都是正确的。

  • 相关阅读:
    MongoDB备份与恢复
    SpringClouldAlibaba 之 Sentinel流控规则同步到nacos(并重新生成镜像)
    zk session expire会引起HA模式的rm一直处于standby吗
    c++ - 第13节 - c++中的继承
    宝宝入托,爸妈要避开这5种心态
    第十二届蓝桥杯模拟赛第二期
    《零基础学机器学习》笔记-第3课-线性回归
    RocketMq概要
    .NET Core多线程 (4) 锁机制
    【Rust】使用HashMap解决官方文档中的闭包限制
  • 原文地址:https://blog.csdn.net/guoxulieying/article/details/133929715