纸上得来终觉浅,绝知此事要躬行。
日常我们写代码时,很容易导致程序出错,而且有些原因很难被我们发现,所以如何调试检查出问题所在是一个关键的技巧。
常见调试方法
print
pdb
ipython
ide
调试经验总结
- 调试只是开发时的使用的方法,线上环境应该记录业务日志,也应该是用
sentry
搜集错误日志,通过这些日志去回溯问题,不应该等出了问题进行线上调试。
参考链接
1. 使用 print 调试
- 通过在指定的区域打印对应输出来定位问题
def div(a, b):
return a / b
def main(a=1, b=0):
print(a, b)
return div(a, b)
if __name__ == '__main__':
main()
2. 使用 pdb 调试
- 对指定位置调试
[escape@localhost ~]$ python test.py
> /Users/escape/Escape/MorePractise/test.py(6)div()
-> return a / b
(Pdb) list
1 import pdb
2
3
4 def div(a, b):
5 pdb.set_trace()
6 -> return a / b
7
8 def main(a=1, b=0):
9 return div(a, b)
10
11 if __name__ == '__main__':
(Pdb) p a
1
(Pdb) p b
0
(Pdb) c
Traceback (most recent call last):
File "test.py", line 12, in <module>
main()
File "test.py", line 9, in main
return div(a, b)
File "test.py", line 6, in div
return a / b
ZeroDivisionError: division by zero
- 也可以单步调试
[escape@localhost ~]$ python -m pdb test.py
> /Users/escape/Escape/MorePractise/test.py(1)<module>()
-> import pdb
(Pdb) help
Documented commands (type help <topic>):
========================================
EOF c d h list q rv undisplay
a cl debug help ll quit s unt
alias clear disable ignore longlist r source until
args commands display interact n restart step up
b condition down j next return tbreak w
break cont enable jump p retval u whatis
bt continue exit l pp run unalias where
Miscellaneous help topics:
==========================
exec pdb
(Pdb) n
> /Users/escape/Escape/MorePractise/test.py(4)<module>()
-> def div(a, b):
(Pdb) n
> /Users/escape/Escape/MorePractise/test.py(7)<module>()
-> def main(a=1, b=0):
(Pdb) list
2
3
4 def div(a, b):
5 return a / b
6
7 -> def main(a=1, b=0):
8 print(a, b)
9 return div(a, b)
10
11 if __name__ == '__main__':
12 main()
(Pdb) n
> /Users/escape/Escape/MorePractise/test.py(11)<module>()
-> if __name__ == '__main__':
(Pdb) j 5
> /Users/escape/Escape/MorePractise/test.py(5)<module>()
-> return a / b
(Pdb) list
(Pdb) list
2
3
4 def div(a, b):
5 return a / b
6
7 -> def main(a=1, b=0):
8 print(a, b)
9 return div(a, b)
10
11 if __name__ == '__main__':
12 main()
(Pdb) c
1 0
Traceback (most recent call last):
File "/Users/escape/.pyenv/versions/3.6.4/lib/python3.6/pdb.py", line 1667, in main
pdb._runscript(mainpyfile)
File "/Users/escape/.pyenv/versions/3.6.4/lib/python3.6/pdb.py", line 1548, in _runscript
self.run(statement)
File "/Users/escape/.pyenv/versions/3.6.4/lib/python3.6/bdb.py", line 431, in run
exec(cmd, globals, locals)
File "<string>", line 1, in <module>
File "/Users/escape/Escape/MorePractise/test.py", line 7, in <module>
def main(a=1, b=0):
File "/Users/escape/Escape/MorePractise/test.py", line 9, in main
return div(a, b)
File "/Users/escape/Escape/MorePractise/test.py", line 5, in div
return a / b
ZeroDivisionError: division by zero
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
> /Users/escape/Escape/MorePractise/test.py(5)div()
-> return a / b
(Pdb) p a
1
(Pdb) p b
0
(Pdb) a
a = 1
b = 0
(Pdb) q
Post mortem debugger finished. The test.py will be restarted
> /Users/escape/Escape/MorePractise/test.py(1)<module>()
-> import pdb
(Pdb) q
3. 使用 ipython 调试
- 使用
ipython
自带的ipdb
进行代码的调试
[escape@localhost ~]$ ipython -i test.py --pdb --no-banner
1 0
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
~/Escape/MorePractise/test.py in <module>()
10
11 if __name__ == '__main__':
---> 12 main()
~/Escape/MorePractise/test.py in main(a, b)
7 def main(a=1, b=0):
8 print(a, b)
----> 9 return div(a, b)
10
11 if __name__ == '__main__':
~/Escape/MorePractise/test.py in div(a, b)
3
4 def div(a, b):
----> 5 return a / b
6
7 def main(a=1, b=0):
ZeroDivisionError: division by zero
> /Users/escape/Escape/MorePractise/test.py(5)div()
3
4 def div(a, b):
----> 5 return a / b
6
7 def main(a=1, b=0):
ipdb> p b
0
ipdb> p a
1
ipdb> q