世界人都知道,程序总会有bug存在。复杂点的bug一般人不能一眼看出,这就一要一套调试程序的手段。

方法一:使用print()函数直接打印:

>>> def foo(s):
... n = int(s)
... print(n)
... return 10 / n
...
>>> def main():
... foo('')
...
>>> main()
0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in main
File "<stdin>", line 4, in foo
ZeroDivisionError: division by zero

我们在认为可能出错的地方打印变量出来。这有很大的弊端,因为打印的代码实际功能并不需要。这都是垃圾信息。

方法二:用断言assert代替打印print()

>>> def foo(s):
... n = int(s)
... assert n != 0,'n的值是0!'
... return 10 / n
...
>>> def main():
... foo('')
...
>>> main()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in main
File "<stdin>", line 3, in foo
AssertionError: n的值是0!

assert的意思是,紧跟其后的表达式的结果应该是true,否则会抛出AssertionError。这里 n = 0,所以结果是AssertionError: n的值是0!

如果assert仅仅这样的话,那和print区别也不大嘛。下面就是assert特点喽:启动python解释器的时候可以用-O参数来关闭assert(这是大写的字母O;关闭后,可以把assert的语句当做pass用),将上述代码放进新建文件err_assert.py中,执行结果:

PS E:\Python3.6.3\workspace> python -O err_assert.py
Traceback (most recent call last):
File "err_assert.py", line 9, in <module>
main()
File "err_assert.py", line 7, in main
foo('')
File "err_assert.py", line 4, in foo
return 10 / n
ZeroDivisionError: division by zer

方法三:用logging替换print(),和assert比,logging不会抛出错误,而是可以输出到文件中

新建一个err_logginginfo.py文件:

import logging
logging.basicConfig(level=logging.INFO)
s = '0'
n = int(s)
logging.info('n=%d' % n)
print(10/n) #执行结果
PS E:\Python3.6.3\workspace> python err_logginginfo.py
INFO:root:n=0
Traceback (most recent call last):
File "err_logginginfo.py", line 6, in <module>
print(10/n)
ZeroDivisionError: division by zero

logging可以允许你指定记录信息的级别,级别由低到高分别有debug、info、warning、error、CRITICAL等级别,定义为高级别的时候,低级别的信息就不在显示了。比如,我们调整为WARNING级别,看看INFO还有作用吗:

import logging
logging.basicConfig(level=logging.WARNING)
s = ''
n = int(s)
logging.info('n=%d' % n)
print(10/n)

执行结果:

PS E:\Python3.6.3\workspace> python err_logginginfo.py
Traceback (most recent call last):
File "err_logginginfo.py", line 6, in <module>
print(10/n)
ZeroDivisionError: division by zero

这样,我们可以放心输出不同级别的信息,也不用删除。统一的控制输出哪个级别的信息。

上述例子中,logging都是把结果输出到控制台console,logging可实现的作用非常丰富,例如,我们简单配置后,还可以把结果输出到文件,甚至通过tcp协议,将日志内容发送到网络。

方法四:使用python的调试器pdb,可以让程序以单步方式执行,方便我们随时查看运行状态。

新建程序err_pdb.py文件:

s = ''
n = int(s)
print(10 / n)

然后以pdb模式启动:

PS E:\Python3.6.3\workspace> python -m pdb err_pdb.py
> e:\python3.6.3\workspace\err_pdb.py(1)<module>()
-> s = ''
(Pdb) l
1 -> s = ''
2 n = int(s)
3 print(10 / n)
[EOF]
(Pdb) n
> e:\python3.6.3\workspace\err_pdb.py(2)<module>()
-> n = int(s)
(Pdb) p s
''
(Pdb) p n
*** NameError: name 'n' is not defined
(Pdb) n
> e:\python3.6.3\workspace\err_pdb.py(3)<module>()
-> print(10 / n)
(Pdb) p n
0
(Pdb) p s
''
(Pdb) n
ZeroDivisionError: division by zero
> e:\python3.6.3\workspace\err_pdb.py(3)<module>()
-> print(10 / n)
(Pdb) n
--Return--
> e:\python3.6.3\workspace\err_pdb.py(3)<module>()->None
-> print(10 / n)
(Pdb) n
ZeroDivisionError: division by zero
> <string>(1)<module>()->None
(Pdb) n
--Return--
> <string>(1)<module>()->None
(Pdb) n
Traceback (most recent call last):
File "E:\Python3.6.3\lib\pdb.py", line 1667, in main
pdb._runscript(mainpyfile)
File "E:\Python3.6.3\lib\pdb.py", line 1548, in _runscript
self.run(statement)
File "E:\Python3.6.3\lib\bdb.py", line 431, in run
exec(cmd, globals, locals)
File "<string>", line 1, in <module>
File "e:\python3.6.3\workspace\err_pdb.py", line 3, in <module>
print(10 / n)
ZeroDivisionError: division by zero
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
> e:\python3.6.3\workspace\err_pdb.py(3)<module>()->None
-> print(10 / n)
(Pdb) q
Post mortem debugger finished. The err_pdb.py will be restarted
> e:\python3.6.3\workspace\err_pdb.py(1)<module>()
-> s = ''
(Pdb) n
> e:\python3.6.3\workspace\err_pdb.py(2)<module>()
-> n = int(s)
(Pdb) q
PS E:\Python3.6.3\workspace>

小写字母l,可以列出所有要执行的代码;

n 命令表示单步执行代码;

p 后面加上变量名,可以随时查看变量的值;

在pdb模式中,对于还没有单步执行到的代码,相关的变量的变更是无效的;

q 命令退出当前调试,进入重新从头开始调试,再次输入q,就会推出调试程序。

这种方式的调试,有一个弊端,就是只能一步一步的执行下去,如果程序有很多行,岂不是累死。

方法五:在可能出错的地方使用pdb.set_trace(),就可以设置一个断电:

#err_pdb.py
import pdb s = ''
n = int(s)
pdb.set_trace() #程序运行到这里会自动停止,等待命令
print(10 / n)

这时,我们可以使用l、c、n、p、q等命令来控制和查看程序:

PS E:\Python3.6.3\workspace> python err_pdb.py
> e:\python3.6.3\workspace\err_pdb.py(7)<module>()
-> print(10 / n)
(Pdb) p s
''
(Pdb) l
2 import pdb
3
4 s = ''
5 n = int(s)
6 pdb.set_trace() #程序运行到这里会自动停止,等待命令
7 -> print(10 / n)
[EOF]
(Pdb) n
ZeroDivisionError: division by zero
> e:\python3.6.3\workspace\err_pdb.py(7)<module>()
-> print(10 / n)
(Pdb) c
Traceback (most recent call last):
File "err_pdb.py", line 7, in <module>
print(10 / n)
ZeroDivisionError: division by zero

方法六:中级调试武器,IDE。省略若干网页……

python错误调试print、assert、logging、pdb、pdb.set_trace()的更多相关文章

  1. Python错误调试-raise、assert

    raise: raise语句手工引发一个异常:,这样做程序不会因异常而终止,而是运行报错 1 "raise" [expression ["," expressi ...

  2. python错误、调试、测试

    1.错误, Python内置的try...except...finally用来处理错误十分方便.出错时,会分析错误信息并定位错误发生的代码位置才是最关键的. 程序也可以主动抛出错误,让调用者来处理相应 ...

  3. Python学习 Day 12 调试 断言 logging pdb pdb.set_trace

    调试 第一种方法简单直接粗暴有效,就是用print把可能有问题的变量打印出来看看: >>> def foo(s): n= int(s) print '>>> n = ...

  4. python: 错误处理try详解 ,traceback调用栈, 调试(logging)

    摘录:https://www.liaoxuefeng.com/wiki/1016959663602400/1017598873256736 错误处理 调试 错误处理 高级语言都会使用内置的一套try. ...

  5. Pdb— Python的调试器

    参考:Pdb- Python的调试器 pdb 模块定义了一个交互式源代码调试器,用于 Python 程序.它支持在源码行间设置(有条件的)断点和单步执行,检视堆栈帧,列出源码列表,以及在任何堆栈帧的上 ...

  6. python之错误调试

    无论谁写的程序,必定会存在bug,解决bug需要我们去调试程序.于是乎,在Python中,就会好几种调试手段,如print.assert.logging.pdb.pdb.set_trace() 一.使 ...

  7. 转 Python3 错误和异常/ Python学习之错误调试和测试

    ########sample 0 https://www.cnblogs.com/Simon-xm/p/4073028.html except: #捕获所有异常 except: <异常名> ...

  8. Python错误处理和调试

    错误处理(try...except...finally...) try: print('try...') r = 10 / 0 print('result:', r) except ZeroDivis ...

  9. Python错误、调试和测试

    try: print('try...') r = 10 / int('a') print('result:', r) except ValueError as e: print('ValueError ...

随机推荐

  1. CSP2019,RP+=150。

    csp2019游记 第一题水死了,2分钟过! 第二题被卡住了,才得了30分. 第三题背包DP,可惜了,出了考场才知道... 第四题骗到20分,也算心满意足了.. 150,省二左右,辣鸡... 反正就是 ...

  2. MySQL多索引查询选择

    MySQL多索引查询选择 MySQL选择索引-引入 我们知道我们一个表里面可以有多个索引的,那么我们查询数据的时候不指定索引,MySQL就会帮我们自动选择.既然是MySQL程序帮我们自动选择的那么会不 ...

  3. Python内置类属性,元类研究

    Python内置类属性 我觉得一切都是对象,对象和元类对象,类对象其实都是一样的,我在最后进行了证明,但是只能证明一半,最后由于元类的父类是type,他可以阻挡对object属性的访问,告终 __di ...

  4. php-fpm的pool、php-fpm慢执行日志、open_basedir、php-fpm进程管理

    6月13日任务 12.21 php-fpm的pool12.22 php-fpm慢执行日志12.23 open_basedir12.24 php-fpm进程管理 12.21 php-fpm的pool p ...

  5. C语音I博客作业09

    ------------恢复内容开始------------ 这个作业属于那个课程|C语言程序设计II --|:--:|--: 这个作业要求在哪里|https://edu.cnblogs.com/ca ...

  6. activate-power-mode,让你在Python编码中,感受炫酷的书写特效!

    Atom Atom 是github专门为程序员推出的一个跨平台文本编辑器,具有简洁和直观的图形用户界面,并有很多有趣的特点:支持CSS,HTML,JavaScript等网页编程语言.说到这里大家以为我 ...

  7. SpringBoot使用注解(@value)读取properties(yml)文件中 配置信息

    为了简化读取properties文件中的配置值,spring支持@value注解的方式来获取,这种方式大大简化了项目配置,提高业务中的灵活性. 1. 两种使用方法1)@Value("#{co ...

  8. js 防抖、截流

    突发奇想,在触发事件的时候,一些会频繁触发的事件会不会造成资源的浪费或者大量的计算造成页面卡顿,比如onresize,onscroll,onmousemove等事件. 然后就引出了一个新知识点:防抖. ...

  9. three.js各种材质的实现源码

    three.js常用材质:基本材质.兰伯特材质.冯氏材质.标准材质. 我们可以自己使用着色器实现这些材质,用于批量渲染等用途. 为了简单,假设物体只有一张漫反射贴图,场景中只存在一个环境光和一个平行光 ...

  10. PyCharm设置Python版本,你肯定不知道!

      前言本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理.作者:智小星    PyCharm默认会使用虚拟的Python解释器,即使 ...