python错误、调试、测试

错误:
1、程序编写有问题造成的:即bug
2、用户输入造成的:需要检查输入
3、完全无法在程序运行过程中预测的:
磁盘满、网络断掉。这类错误也称为异常,在程序中通常是必须处理的,否则,程序会因为各种问题终止并退出。

解决办法
1、跟踪程序的执行,查看变量的值是否正确,这个过程称为调试。 2、Python的pdb可以让我们以单步方式执行代码。

错误处理

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

  • Python的错误其实也是class,所有的错误类型都继承自BaseException,所以在使用except时需要注意的是,它不但捕获该类型的错误,还把其子类也“一网打尽”。

使用try...except可以跨越多层调用
try:
    print('try...')
    r = 10 / int('2')
    print('result:', r)
except ValueError as e:
    print('ValueError:', e)# int()函数可能会抛出ValueError
except ZeroDivisionError as e:# 捕获除以零的时候的错误
    print('ZeroDivisionError:', e)
else:
    print('no error!')
finally:
    print('finally...')
print('END')
发生了不同类型的错误,应该由不同的except语句块处理
当没有错误发生时,会自动执行else语句

使用try…except捕获错误还有一个巨大的好处,就是可以跨越多层调用,比如函数main()调用bar(),bar()调用foo(),结果foo()出错了,这时,只要main()捕获到了,就可以处理:

def foo(s):
    return 10 / int(s)

def bar(s):
    return foo(s) * 2

def main():
    try:
        bar('0')
    except Exception as e:
        print('Error:', e)
    finally:
        print('finally...')

调用栈

  • 如果错误没有被捕获,它就会一直往上抛,最后被Python解释器捕获,打印一个错误信息,然后程序退出。
  • 出错的时候,一定要分析错误的调用栈信息,才能定位错误的位置
# err.py:
def foo(s):
    return 10 / int(s)

def bar(s):
    return foo(s) * 2

def main():
    bar('0')

main()

执行,异常栈信息如下
$ python3 err.py
Traceback (most recent call last):
  File "err.py", line 11, in <module>
    main()
  File "err.py", line 9, in main
    bar('0')
  File "err.py", line 6, in bar
    return foo(s) * 2
  File "err.py", line 3, in foo
    return 10 / int(s)
ZeroDivisionError: division by zero
Python内置的logging模块
既然我们能捕获错误,就可以把错误堆栈打印出来,然后分析错误原因,
同时,让程序继续执行下去。
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')
同样是出错,但程序打印完错误信息后会继续执行,并正常退出:
通过配置,logging还可以把错误记录到日志文件里,方便事后排查。
raise 
抛出错误
错误是class,捕获一个错误就是捕获到该class的一个实例。因此,
错误并不是凭空产生的,而是有意创建并抛出的

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

$ python3 err_raise.py 
Traceback (most recent call last):
  File "err_throw.py", line 11, in <module>
    foo('0')
  File "err_throw.py", line 8, in foo
    raise FooError('invalid value: %s' % s)
__main__.FooError: invalid value: 0

捕获完毕,进行抛出
捕获错误目的只是记录一下,便于后续追踪。但是,由于当前函数不知道
应该怎么处理该错误,所以,最恰当的方式是继续往上抛,让顶层调用者去处理。
raise语句如果不带参数,就会把当前错误原样抛出。
# err_reraise.py

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

调试

使用print()

def foo(s):
    n = int(s)
    print('>>> n = %d' % n)
    return 10 / n

def main():
    foo('0')

main()

使用断言


判断flase,assert语句本身就会抛出AssertionError:
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!

启动Python解释器时可以用-O参数来关闭assert:
$ python -O err.py

logging

允许你指定记录信息的级别,有debug,info,warning,error等几个级别,这样一来,你可以放心地输出不同级别的信息,也不用删除,最后统一控制输出哪个级别的信息。

assert比,logging不会抛出错误,而且可以输出到文件:

import logging
logging.basicConfig(level=logging.INFO)
#当我们指定level=INFO时,logging.debug就不起作用了。同理,指定level=WARNING后,debug和info就不起作用了

s = '0'
n = int(s)
logging.info('n = %d' % n)
print(10 / n)

$ python err.py
INFO:root:n = 0
Traceback (most recent call last):
  File "err.py", line 8, in <module>
    print(10 / n)
ZeroDivisionError: division by zero

调试器pdb

调试器pdb
启动-m pdb
$ python -m pdb err.py

输入1查看代码
输入n单步执行代码
p 变量名来查看变量
输入命令q结束调试
设置断点:在可能出错的地方放一个pdb.set_trace()
        可以用命令p查看变量,或者用命令c继续运行:

IDE

单元测试

  • 单元测试是用来对一个模块、一个函数或者一个类来进行正确性检验的测试工作。
  • 比如对函数abs(),我们可以编写各种数值测试这个函数

未完

文档测试

未完

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王蒟蒻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值