zoukankan      html  css  js  c++  java
  • 第八章-错误调试

    1 错误处理

    1.1 异常捕捉

      在Python中有try..except..else..finally用于捕捉异常和处理异常

      try后面接需要处理异常的语句

      except后面是对异常进行处理的, 具体有两个形式

        1) 方法一

    except 异常名字 as e:
        print(e)

        2)方法二

    except:
        print("出现异常")

      else是当没有出现异常的时候执行该体内的语句

      finally是不管出不出现异常都会执行

      异常都是继承自BaseException

      except可以有多个, 但是顺序很重要, 如果前面的是父类的异常, 那么在之后的子类的异常就处理不到了

      因此先写类型小的异常, 再写类型大的异常

      具体的异常的继承关系

      try..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 抛出异常

      有的时候异常不一定非要在本位置处理, 可以抛出异常给上一级处理

      抛出异常用raise

      具体的使用方法

    raise 异常名字(需要传递的异常信息)

      可以通过定义类的方式定义一个自定义的异常, 自定义错误类需要继承一个错误

    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.3 记录错误

      可以通过logging模块来讲错误信息保存在日志文件中

      这样函数不仅记录了错误信息, 程序就算发生了异常也可以正常运行

      具体使用格式

    import logging
    ...
    logging.exception(异常对象)

      具体代码如下

    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')
    

    2 调试

    2.1 断言

      断音使用关键字assert

      断言后面跟一个判断表达式

      判断表达式为True表示能够正常执行, 为False就会出现AssertionError异常

      断言判断表达式后面可以接一个提示信息, 用于出现异常的情况, 将该信息放到AssertionError后, 这俩之间用逗号分隔

      具体格式如下

    assert 判断表达式, 异常提示字符串

      如果assert过多, 可以在执行py文件的时候加入-o参数来忽略断言

    python3 -O py文件

    2.2 logging

      在logging模块中还可以记录不同级别的信息

      logging的信息有debug, info, warning, error四种级别的信息

      可以通过

    logging.basicConfig(level=logging.级别名字)

      来指定输出的级别信息, 设置之后在该级别前面的级别的信息就不起作用了

    3 单元测试

      单元测试是一种测试驱动开发的模式

      可以确保程序模块符合测试用例

      在模块修改的时候也可以在重新运行一下单元测试, 很方便

      Python中的unittest模块就是编写单元测试的

      单元测试的类名, 方法名(尤其是)都最好是以test开头

      测试的类需要继承 unittest.TestCase

      继承之后会有两个特殊地函数 setUp() 和 tearDown() 函数

      这两个函数分别是在测试前和测试后执行

      主要适用于在开始前后的准备和结束代码

      下面是模拟dict的代码

    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
    

      下面是测试该代码的单元测试

    import unittest
    
    from mydict import Dict
    
    class TestDict(unittest.TestCase):
    
        def setUp(self):
            print('setUp...')
    
        def tearDown(self):
            print('tearDown...')
    
        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
    
    if __name__ == '__main__':
        unittest.main()
    

    4 文档测试

      在定义某些类的时候, 可以通过'''说明信息'''来形成__doc__

      可以在该部分写入一些测试代码, 类似于交互式环境的代码

      通过Python内置的文档测试, 可以运行那些测试代码, 来更加快速的检验代码的正确性

      具体写入的代码中如果输出结果较多, 可以用...来代替

      具体如下

    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()
    

      运行该代码后如果没有输出, 则一切正常

      文档测试只会在命令直接运行时才会执行, 正常导入模块是不会执行的

    人若有恒 无所不成
  • 相关阅读:
    nrm安装与配置(nrm管理npm源)
    Mac启动MongoDB报错:exception in initAndListen: NonExistentPath: Data directory /data/db not found., terminating
    基本类型(例如:int)数组和ArrayList之间的转化
    sqlite3--sqlite3_prepare
    fgets
    strdup
    openssl-EVP_md5()
    FIPS--Federal Information Processing Standards
    pthread_mutexattr_gettype、pthread_mutexattr_settype、pthread_mutexattr_destroy、pthread_mutexattr_init!
    gethostname&&getdomainname
  • 原文地址:https://www.cnblogs.com/weihuchao/p/6731000.html
Copyright © 2011-2022 走看看