美文网首页
Python 错误、调试和测试

Python 错误、调试和测试

作者: _YZG_ | 来源:发表于2017-12-28 19:47 被阅读10次

错误处理

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

记录错误
Python内置的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')

自己定义错误
class FooError(ValueError):
    pass

def foo(s):
    n = int(s)
    if n==0:
        raise FooError('invalid value: %s' % s)
    return 10 / n

foo('0')

直接把错误抛到上层
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()


可以把一个类型的错误转换成另一种类型
try:
    10 / 0
except ZeroDivisionError:
    raise ValueError('input error!')

调试

断言
def foo(s):
    n = int(s)
    assert n != 0, 'n is zero!'
    return 10 / n

def main():
    foo('0')
assert的意思是,表达式n != 0应该是True,否则,根据程序运行的逻辑,后面的代码肯定会出错。

如果断言失败,assert语句本身就会抛出AssertionError:
$ python err.py
Traceback (most recent call last):
  ...
AssertionError: n is zero!

可以用-O参数来关闭assert
$ python -O err.py



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)

这就是logging的好处,它允许你指定记录信息的级别,有debug,info,warning,error等几个级别,当我们指定level=INFO时,logging.debug就不起作用了。
同理,指定level=WARNING后,debug和info就不起作用了。
这样一来,你可以放心地输出不同级别的信息,也不用删除,最后统一控制输出哪个级别的信息。

logging的另一个好处是通过简单的配置,一条语句可以同时输出到不同的地方,比如console和文件。



pdb
$ python -m pdb err.py

# err.py
s = '0'
n = int(s)
print(10 / n)

输入命令l来查看代码
(Pdb) l
  1     # err.py
  2  -> s = '0'
  3     n = int(s)
  4     print(10 / n)

输入命令n可以单步执行代码

任何时候都可以输入命令p 变量名来查看变量:
(Pdb) p s
'0'
(Pdb) p n
0

输入命令q结束调试,退出程序:

(Pdb) q


pdb.set_trace()
这个方法也是用pdb,但是不需要单步执行,我们只需要import pdb,然后,在可能出错的地方放一个pdb.set_trace(),就可以设置一个断点:
# err.py
import pdb

s = '0'
n = int(s)
pdb.set_trace() # 运行到这里会自动暂停
print(10 / n)

运行代码,程序会自动在pdb.set_trace()暂停并进入pdb调试环境,可以用命令p查看变量,或者用命令c继续运行:

单元测试

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

编写单元测试时,我们需要编写一个测试类,从unittest.TestCase继承。

以test开头的方法就是测试方法,不以test开头的方法不被认为是测试方法,测试的时候不会被执行。

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

另一种重要的断言就是期待抛出指定类型的Error,比如通过d['empty']访问不存在的key时,断言会抛出KeyError:

with self.assertRaises(KeyError):
    value = d['empty']

而通过d.empty访问不存在的key时,我们期待抛出AttributeError:

with self.assertRaises(AttributeError):
    value = d.empty


运行单元测试

在最后加上两行代码,就可以当做正常的Python脚本运行
if __name__ == '__main__':
    unittest.main()

第二种方法加入-m unittest
$ python -m unittest mydict_test



setUp与tearDown

这两个方法会分别在每调用一个测试方法的前后分别被执行
class TestDict(unittest.TestCase):

    def setUp(self):
        print('setUp...')

    def tearDown(self):
        print('tearDown...')

文档测试

当模块正常导入时,doctest不会被执行。只有在命令行直接运行时,才执行doctest。所以,不必担心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()


相关文章

  • python错误、调试和测试

    错误处理 try与其他语言一样,python也有错误捕获的功能 Python的错误其实也是class,所有的错误类...

  • Python 错误、调试和测试

    错误处理 调试 单元测试 文档测试

  • Python错误、调试和测试

    常见Excpte 内置 try...except...finally 记录错误 Python内置的logging模...

  • Python错误、调试和测试

    @[toc] 1.错误处理 1.1try...except...finally...的错误处理机制 当我们认为某些...

  • Python学习之错误调试和测试

    在程序运行过程中,总会遇到各种各样的错误,Python内置了一套异常处理机制,来帮助我们进行错误处理。 错误处理 ...

  • 软件测试理论

    测试和调试的区别 测试:发现程序的错误 调试:定位和纠正错误(保证软件的正常运行) 软件的危机 软件开发的费用超支...

  • 错误、调试和测试

    错误处理 在程序运行的过程中,如果发生错误,可以事先约定返回一个错误代码,这样就可以知道是否有错,以及出错的原因。...

  • 错误、调试和测试

    高级语言通常都内置了一套try...except...finally...的错误处理机制,Python也不例外。 ...

  • 错误、调试和测试

    错误处理 在程序运行的过程中,如果发生了错误,可以事先约定返回一个错误代码,这样,就可以知道是否有错,以及出错的原...

  • 2022-08-18

    又是轻松的随笔时间。 8月更新: ##就是鸽了(19-21日)Python系列:函数式编程、错误、调试和测试、IO...

网友评论

      本文标题:Python 错误、调试和测试

      本文链接:https://www.haomeiwen.com/subject/ovuugxtx.html