查看变量值和变量类型是否符合我们预期是DEBUG过程中一项非常重要的工作或目的,很多刚接触编程语言的人员习惯于采用print输出中间变量值或者变量类型,
1def test(): 2 x, y = 1, 2 3 z = x + y 4 print(z) 5 6 7if __name__ == '__main__': 8 test()
输出:
1>>> 3
用print进行debug虽然简单,但是却有很多弊端:
- 输出信息多而杂乱
- 需要在变量处反复注释取消注释,过程繁琐
02
logging
更近一层的开发人员会选择用log日志的方式进行debug,通过对输出日志设置DEBUG、INFO、WARNING、ERROR、CRITICAL等级别来控制日志的输出,当输出级别小于设置级别时信息不会输出,当级别在设置级别之上时才会被输出,级别大小依次是DEBUG<INFO<WARNING<ERROR<CRITICAL,因此,当级别设置为logging.INFO时,DEBUG级别就不会输出,WARNING、ERROR、CRITICAL会输出,通过这种方式避免不同场景下输出内容杂乱的问题。
1import logging 2 3logging.basicConfig(level=logging.INFO) 4 5 6def test(): 7 x, y = 1, 2 8 z = x + y 9 logging.debug(" debug z value : {}".format(z)) 10 logging.warning(" warning z value : {}".format(z)) 11 logging.error(" error z value : {}".format(z)) 12 logging.critical(" critical z value : {}".format(z)) 13 14 15if __name__ == '__main__': 16 test()
输出:
1>>> WARNING:root: warning z value : 3 2>>> ERROR:root: error z value : 3 3>>> CRITICAL:root: critical z value : 3
03
IDE
目前很多入门或者深入Python的开发者都选择使用一些成熟的IDE进行开发,例如pycharm。它自带debug工具,因此就不需要在代码中大量的使用print、logging字段,减少了代码的繁琐性。
例如图中所示:
- 通过点击左侧栏设置断点(1)
- 点击2所示图标进行debug
- 通过3选择要执行的动作
- Step over--下一步
- Step into--进入函数
- Step out--执行剩余部分然后跳出函数
- Run to cursor--执行到光标处
- 通过4的variables查看当前所有变量
- 通过5的"+"添加特定要查看的变量
不得不承认,IDE的debug工具的确很强大、而且很好用,但是我认为这样有一个弊端,就是过度依赖IDE,如果没有IDE的话却不知道从何下手,然后不得不回到最原始的print、log方式。
04
pdb
当脱离高效的IDE之后,该怎么进行DEBUG?
很多人喜欢用sublime、vim等纯文本编辑器,这些编辑器本身是不具备pycharm这样高效的debug工具的,那该怎么样使得这些文本编辑器也可以用于Python的debug呢?接下来就介绍一个Python自带的基础工具包pdb。
pdb的使用有两种方式:
- 命令行方式
- 直接导入pdb包
命令行模式直接在命令行下输入下面命令即可,
1python -m pdb xxx.py
其中xxx.py指的是需要调试的Python程序。
直接导入pdb包的方式如下,
1# 导入pdb包 2import pdb 3 4# 设置断点 5pdb.set_trace() 6 7# 执行程序 8Python xxx.py
pycharm支持Step over、Step into、Step out等快捷方式,pdb是不是仅仅支持set_trace设置断点这么弱?当然不是!
pdb支持丰富而强大的调试命令:
命令 | 功能 |
n | 执行下一条语句,相当于Step over |
s | 相当于Step into |
r | 执行当前函数剩余部分,相当于Step out |
l | 列出代码片段 |
c | 执行到下一个断点 |
a | 列出可执行的函数 |
pp | 输出变量值 |
q | 退出debug |
对于命令行模式还可以使用如下命令:
命令 | 功能 |
b | 添加断点: b LineNumber:在指定行添加断点 b FileName:LineNumber:在指定文件的指定行添加断点 b 列出当前所有断点 |
tbreak | 设置临时断点 |
cl | 清楚断点 |
disable | 停用断点 |
enable | 激活断点 |
下面就来演示一下:
1import pdb 2 3 4def add(x, y) 5 k = 10 6 z = x + y 7 for i in range(k): 8 pdb.set_trace() 9 z += i 10 return z 11 12def main(): 13 x, y = 1, 2 14 pdb.set_trace() 15 z = add(x, y) 16 print(z) 17 18if __name__ == '__main__': 19 main()
执行程序,到达第一个断点处:
1python test.py
2> d:\pycharmprojects\learning\test.py(15)main()
3-> z = add(x, y)
进入add函数(step into):
1(Pdb) s 2--Call-- 3> d:\pycharmprojects\learning\test.py(4)add() 4-> def add(x, y):
下一行(step over):
1(Pdb) 2> d:\pycharmprojects\learning\test.py(6)add() 3-> z = x + y
执行到z=x+y这一行,然后跳过当前函数,执行剩余部分(step out):
1(Pdb) r 2--Return-- 3> d:\pycharmprojects\learning\test.py(10)add()->48 4-> return z
输出变量:
1(Pdb) pp z 248
列出当前代码片段:
1(Pdb) l 2 5 k = 10 3 6 z = x + y 4 7 for i in range(k): 5 8 pdb.set_trace() 6 9 z += i 7 10 -> return z 8 11 9 12 def main(): 10 13 x, y = 1, 2 11 14 pdb.set_trace() 12 15 z = add(x, y)
上述就介绍了一种高效的Python调试工具包,对于喜欢用文本编辑器进行程序开发的人员来说,这是非常实用而且高效的方式,能够针对性的设置断点、输出变量值,不用繁琐、杂乱的使用print、log方式。
当然,除了pdb之外还有很多高校的Python调试工具包,后续会单独介绍一种更为简单高效的Python调试工具。