关于python:Python也有pdb

5次阅读

共计 7390 个字符,预计需要花费 19 分钟才能阅读完成。

C 有 gdb,Python 也有 pdb

写过 C 语言的同学们想必都很思念(读者:¿)gdb 调试器,应用 gdb 能够随便在程序运行过程中暂停流程、查看变量。

很多时候,咱们单纯剖析代码流程和日志信息无奈定位的问题,都得靠调试器来帮忙;能够说有了调试器,程序员才是代码世界残缺的上帝。

Python 当然也不逞强,同样存在这样的巴别塔能够让人升天

01
——不过必须抵赖的是,古代 IDE 集成的图形化调试性能曾经很好使了,个别状况下应用命令行工具的场景并不多。

然而也的确存在无奈应用图形化 IDE 的状况,因而对 pdb 工具略作理解还是很有必要的。毕竟谁也不晓得可能被扔给一个什么样的环境啊哈哈

pdb 的应用
作为解释型语言,Python 调试工具的应用跟 gdb 毕竟还是有区别的。

比方 Python 的调试就不须要什么符号表之类的货色,说到底,最终 Python 虚拟机执行的逻辑也是自带符号的。

也正是因为 Python 的这种特殊性,所有 pdb 其实有两种不太一样的应用形式,即侵入式和非侵入式。

其实按字面意思就很容易了解在两种形式的应用。类比一下脑机接口,也分为侵入式和非侵入式。侵入式就示意要将电极、芯片植入大脑皮层,“侵入”人体;而非侵入式则是在头骨外收集脑电波进行剖析。

同样地,侵入式 pdb 调用就是将调用 pdb 的代码间接写入 Python 脚本当中;而非侵入式则是从命令行调用 pdb,执行相应被调试脚本。

  1. 侵入式 pdb

应用形式如下代码所示,在代码中途插入一行调用:

import pdb; # pdb.set_trace()


a = "just"
b = "do"

pdb.set_trace()

c = ['p', 'y', 't', 'h', 'o', 'n']
print(a)

运行脚本,会进入这样一个交互式界面:

D:\000-GitHub\python-examples\xuanyuanyulong\2020-11-04-python-pdb>python test_pdb_intrusive.py
> d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py(21)<module>()
-> c = ['p', 'y', 't', 'h', 'o', 'n']
(Pdb)

到这里曾经启动了 pdb,并且打印内容中 -> c = [‘p’, ‘y’, ‘t’, ‘h’, ‘o’, ‘n’]行首的箭头,示意以后程序执行流到了这一行代码,如果继续执行,将首先执行该行。

  1. 非侵入式 pdb

非侵入式要 xue 微简略一些,最大的益处是不须要改变代码。

咱们在控制台执行以下命令:

D:\000-GitHub\python-examples\xuanyuanyulong\2020-11-04-python-pdb>python -m pdb test_pdb_intrusive.py
> d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py(1)<module>()
-> import pdb; # pdb.set_trace()
(Pdb)

能够看到,通过这种形式进入调试,程序执行流停在了程序结尾。

通过剖析进入调试时代码执行流的地位,咱们能够发现,实际上侵入式的插入 pdb.set_trace()调用,等价于咱们从命令行启动 pdb,而后在这个调用的下一行打了一个断点,而后间接运行程序。

简略命令
gdb 中有一些罕用的简略命令,本节阿酱带大家相熟一下,后续会做更深刻的探讨。

  1. h(elp)

在 pdb 界面下输出 h 或 help 命令,即可列出 pdb 中反对的各种命令:

(Pdb) h

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 后带一个命令作为参数,还可进一步看到相应的应用阐明:

(Pdb) h h
h(elp)
        Without argument, print the list of available commands.
        With a command name as argument, print help about that command.
        "help pdb" shows the full pdb documentation.
        "help exec" gives help on the ! command.

置信我,help 其实才是 pdb 外面最重要的命令。别的什么都能够记不住,然而 help 肯定要记住。在以后果为导向的职场生存中也是一样,遇到问题要及时求助哟~

  1. l(ist)

打印以后文件的源代码。不带参数的话,默认打印以后行前后共计 11 行代码。继续执行该命令的话,则会持续往后打印最多 11 行代码,直到遇上文件结束符 EOF。

用. 作为参数则限定要强一点,只会打印以后行前后 11 行代码。

(Pdb) l
  1  -> import pdb; # pdb.set_trace()
  2
  3
  4     def addStr(a, b):
  5         return a + b
  6
  8         return ''.join(l)
  9
 10     def getSlogan(a, b, c):
 11         result = addStr(a, b) + mergeChar(c)

当指定两个参数时,则打印这个区间内的代码:

(Pdb) l 3, 7
  3
  4     def addStr(a, b):
  5         return a + b
  6
  7  -> def mergeChar(l: list):

而当第二个参数 b 比第一个参数 a 小的时候,则示意“从第 a 行开始,持续往后打印 b 行”,也就是总共打印 (1+b) 行:

(Pdb) l 7, 3
  7  -> def mergeChar(l: list):
  8         return ''.join(l)
  9
 10     def getSlogan(a, b, c):
  1. p/pp

打印某个对象的值。区别在于 pp 调用的是 pprint 函数,打印更加好看。

(Pdb) p a
'just'
(Pdb) p addStr
<function addStr at 0x000002087B0F9C80>
  1. !

应用! 能够在 pdb 环境下,执行个别的 Python 语句。通常咱们能够用来扭转变量的值——要不怎么说调试器能够让你成为上帝呢?还有比这更随心所欲的吗?

个别的话这个! 其实能够省略,然而当要执行语句结尾的单词与 pdb 的已有命令抵触,就得不到预期后果了,所以倡议还是加上。

这个用! 领起命令的做法跟 vim 编辑器的逻辑很像,能够类比记忆。不相熟的读者能够疏忽。

(Pdb) !a = "python"
(Pdb) p a
'python'
  1. r(eturn)

pdb 中,r 和 return 示意同一个意思,即“运行以后函数直到返回”。

这一点上,r 在 pdb 和 gdb 中的含意是不同的。读者不用在意

  1. run/restart

示意从新运行以后被调试程序。应用这个命令,能够为须要传入参数的脚本传入所需参数。

格局与命令行执行该脚本一样,只是把相应的 python 命令和脚本门路替换为了 run 或 restart。

(Pdb) run a b c d kkk
Restarting test_pdb_intrusive.py with arguments:
        test_pdb_intrusive.py
> d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py(1)<module>()
-> import pdb; # pdb.set_trace()
(Pdb) !import sys
(Pdb) p sys.argv
['test_pdb_intrusive.py', 'a', 'b', 'c', 'd', 'kkk']
  1. b(reak)

查看 / 增加断点。

不带任何参数时,即列出以后已有断点。

(Pdb) b 21
Breakpoint 1 at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21
(Pdb) b 17
Breakpoint 2 at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17
(Pdb) b
Num Type         Disp Enb   Where
1   breakpoint   keep yes   at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21
2   breakpoint   keep yes   at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17

同时,通过 run 和 restart 从新运行被调试程序,不会革除已有断点:

(Pdb) run
Restarting test_pdb_intrusive.py with arguments:
        test_pdb_intrusive.py
> d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py(1)<module>()
-> import pdb; # pdb.set_trace()
(Pdb) b
Num Type         Disp Enb   Where
1   breakpoint   keep yes   at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21
2   breakpoint   keep yes   at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17
  1. cl(ear)

有三种应用形式:1)相似设置断点时,革除特定文件特定行的断点;2)将要革除的断点号列出来,以空格分隔;3)不带参数,革除所有断点。

上面一一演示:

1)相似设置断点时,革除特定文件特定行的断点

(Pdb) b
Num Type         Disp Enb   Where
1   breakpoint   keep yes   at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21
2   breakpoint   keep yes   at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17
(Pdb) clear test_pdb_intrusive.py:21
(Pdb) b
Num Type         Disp Enb   Where
2   breakpoint   keep yes   at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17

2)将要革除的断点号列出来,以空格分隔

(Pdb) b 21
Breakpoint 3 at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21
(Pdb) b 15
Breakpoint 4 at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:15
(Pdb) b
Num Type         Disp Enb   Where
2   breakpoint   keep yes   at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17
3   breakpoint   keep yes   at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21
4   breakpoint   keep yes   at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:15
(Pdb) clear 2 4
Deleted breakpoint 2 at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17
Deleted breakpoint 4 at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:15
(Pdb) b
Num Type         Disp Enb   Where
3   breakpoint   keep yes   at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21

3)不带参数,革除所有断点

(Pdb) b 17
Breakpoint 5 at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17
(Pdb) b 15
Breakpoint 6 at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:15
(Pdb) b
Num Type         Disp Enb   Where
3   breakpoint   keep yes   at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21
5   breakpoint   keep yes   at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17
6   breakpoint   keep yes   at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:15
(Pdb) b
Num Type         Disp Enb   Where
3   breakpoint   keep yes   at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21
5   breakpoint   keep yes   at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17
6   breakpoint   keep yes   at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:15
(Pdb) clear
Clear all breaks? yes
Deleted breakpoint 3 at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:21
Deleted breakpoint 5 at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:17
Deleted breakpoint 6 at d:\000-github\python-examples\xuanyuanyulong\2020-11-04-python-pdb\test_pdb_intrusive.py:15
(Pdb) b

好了打住打住,写之前感觉 pdb 没多少货色,没想到写起来才发现,这么一点内容就曾经这么多了,明天又熬夜了……

总结
pdb 的内容出其不意地丰盛,还有很多内容在这篇文章中都没能波及。之后会再写一篇以作补充。

软件调试其实也是一门很乏味的学识,当然,也是一门很有用的学识。

以上就是本次分享的所有内容,想要理解更多 python 常识欢送返回公众号:Python 编程学习圈,发送“J”即可收费获取,每日干货分享

正文完
 0