pdb– Python调试器

源代码 Lib / pdb.py


模块pdb为Python程序定义了一个交互式源代码调试器。它支持在源代码行级别设置(条件)断点和单步执行,检查堆栈帧,源代码列表,在任何堆栈帧的上下文中对任意Python代码的评估。它也支持事后调试,并且可以在程序控制下调用.

调试器是可扩展的 – 它实际上被定义为类Pdb。这个目前没有文档但是通过阅读源代码很容易理解。扩展接口使用模块bdbcmd.

调试器的提示符是(Pdb)。在调试器的控制下运行程序的典型用法是:

>>> import pdb>>> import mymodule>>> pdb.run("mymodule.test()")> <string>(0)?()(Pdb) continue> <string>(1)?()(Pdb) continueNameError: "spam"> <string>(1)?()(Pdb)

版本3.3中更改:通过readline模块的Tab-completion可用于命令和命令参数,例如:当前的全局和本地名称是p命令

pdb.py也可以作为脚本调用其他脚本进行调试。例如:

python3 -m pdb myscript.py

当作为脚本调用时,如果被调试的程序异常退出,pdb将自动进入事后调试。在事后调试(正常退出程序之后),pdb将重新启动程序。Automaticrestarting保留pdb的状态(如断点),在大多数情况下比在程序退出时退出调试器更有用.

版本3.2:pdb.py现在接受-c选项执行命令,好像在.pdbrc文件中给出,请参阅调试器命令.

版本3.7中的新功能:pdb.py现在接受-m执行类似于python3 -m模块的选项。与脚本一样,调试器将在模块的第一行之前暂停执行.

从正在运行的程序中进入调试器的典型用法是插入

import pdb; pdb.set_trace()

在您想要进入调试器的位置。然后,您可以按照此语句逐步执行代码,并使用continue命令继续在没有调试器的情况下运行.

版本3.7中的新功能:内置的breakpoint(),当使用默认值调用时,可以使用而不是import pdb; pdb.set_trace().

检查崩溃程序的典型用法是:

>>> import pdb>>> import mymodule>>> mymodule.test()Traceback (most recent call last):  File "<stdin>", line 1, in <module>  File "./mymodule.py", line 4, in test    test2()  File "./mymodule.py", line 3, in test2    print(spam)NameError: spam>>> pdb.pm()> ./mymodule.py(3)test2()-> print(spam)(Pdb)

模块定义了以下功能;每个都以不同的方式进入调试器

pdb.runstatement, globals=None, locals=None

执行statement(在调试器控件下以字符串或代码对象的形式给出)。在执行任何代码之前出现调试器提示;你可以设置断点并键入continue,或者您可以使用stepnext逐步完成声明(所有这些命令都在下面解释)。可选globalslocalsarguments指定执行代码的环境;默认使用的是模块__main__的字典。(参见内置exec()eval()功能的说明。)

pdb.runevalexpression, globals=None, locals=None

评估expression(在调试器控件下以字符串或代码对象的形式给出)。当runeval()返回时,它返回表达式的值。否则此函数类似于run().

pdb.runcallfunction, *args, **kwds

使用given参数调用function(函数或方法对象,而不是字符串)。当runcall()返回时,它返回返回的函数调用。函数输入后立即出现调试器提示.

pdb.set_trace(*, header=None)

在调用堆栈帧中输入调试器。这对于在程序中的给定点处硬编码断点是有用的,即使代码未被调试(例如,当断言失败时)。如果给出,header就在调试开始之前打印到控制台上.

更改版本3.7:仅关键字参数header.

pdb.post_mortemtraceback=None

输入给定traceback对象的事后调试。如果没有给出traceback,它会使用当前正在处理的异常之一(如果要使用默认值则必须处理异常).

pdb.pm

进入sys.last_traceback.

中找到的回溯的事后调试run*函数和set_trace()是用于实例化Pdb类并调用其方法的别名名称。如果你想获得更多的功能,你必须自己做:

class pdb.Pdbcompletekey=”tab”, stdin=None, stdout=None, skip=None, nosigint=False, readrc=True

Pdb是调试器类.

completekey, stdinstdout参数传递给下cmd.Cmd类;看那里的描述

skip参数,如果给出,必须是一个可迭代的glob样式的模块名称模式。调试器不会进入源自与这些模式之一匹配的模块的帧。[1]

默认情况下,Pdb为SIGINT信号设置一个处理程序(当用户在控制台上按 Ctrl-C 时发送该信号)continue command.This允许你按 Ctrl-C 再次进入调试器。如果您希望Pdb不要触摸SIGINT处理程序,请将nosigint设置为true.

readrc参数默认为true并控制Pdb是否会从文件系统中加载.pdbrc文件.

skip

import pdb; pdb.Pdb(skip=["django.*"]).set_trace()

版本3.1中新增:skip论证

版本3.2: nosigint论点。以前,一个SIGINT处理程序从未设置过Pdb

更改版本3.6: readrc参数

run// (statement, globals=None, locals=None
runevalexpression, globals=None, locals=None
runcallfunction, *args, **kwds
set_trace

请参阅上述功能的文档.

Debugger Commands

下面列出了调试器识别的命令。大多数命令可以缩写为一个或两个字母,如图所示;例如h(elp)表示hhelp可以用来输入帮助命令(但不是hehel,也不是HHelpHELP)。命令的参数必须由空格(空格或制表符)分隔。可选参数括在方括号内([])在命令语法中;方括号不得打包。命令语法中的替代项由竖线分隔(|).

输入空行重复输入的最后一个命令。例外:如果lastcommand是list命令,则列出接下来的11行.

调试器无法识别的命令被假定为Python语句并在程序的上下文中执行正在调试。Python语句也可以带有感叹号(!)作为前缀。这是检查正在调试的程序的强大方法;它甚至可以改变变量或调用函数。当在这样的声明中发生异常时,打印异常名称但调试器的状态不变.

调试器支持别名别名可以有参数,允许一个人对上下文的一定程度的适应性调查.

多个命令可以输入一行,用;;分隔。(Asingle ;未被使用,因为它是传递给Python解析器的行中的多个命令的分隔符。)没有智能应用于分离命令;输入在第一个;;对分割,即使它是在一个引用的字符串的中间.

如果文件.pdbrc存在于用户的主目录或currentdirectory,它被读入并执行,就好像它已在调试器提示符下键入一样。这对于别名特别有用。如果两个文件都存在,则首先读取主目录中的一个,并且在那里定义的别名可以被本地文件覆盖.

版本3.2:.pdbrc现在可以包含继续调试的命令,例如如continuenext。以前,这些命令没有效果.

h(elp) [command]

没有参数,打印可用命令列表。使用command asargument,打印有关该命令的帮助。help pdb显示完整文档(pdb模块的文档字符串)。由于command参数必须是标识符,help exec必须输入以获得帮助!命令

w(here)

打印堆栈跟踪,最近的框架位于底部。箭头表示当前帧,它决定了大多数命令的上下文.

d(own) [count]

移动当前帧count(默认值为1)在堆栈轨迹中降低(到较新的帧).

u(p) [count]

移动当前帧count(默认值为1)在堆栈跟踪中向上(对于较旧的帧).

b(reak) [([filename:]lineno | function) [, condition]]

使用lineno参数,在那里设置一个中断当前文件。使用function参数,在第一个可执行语句中使用该函数设置中断。行号可以带有文件名和冒号前缀,以指定另一个文件中的断点(可能是一个尚未加载的文件)。在sys.path上搜索文件。请注意,每个断点都分配了一个所有其他断点命令所引用的数字.

如果存在第二个参数,则它是一个表达式,必须在断点被接受之前评估totrue .

没有参数,列出所有中断,包括每个断点,断点被击中的次数,当前忽略计数,以及相关条件(如果有的话)

tbreak [([filename:]lineno | function) [, condition]]

临时断点,在首次命中时自动删除。参数与break.

cl(ear) [filename:lineno | bpnumber [bpnumber ...]]

相同,使用filename:lineno参数,清除此行的所有断点。使用空格分隔的断点号列表,清除这些断点。没有参数,清除所有中断(但首先要求确认).

disable [bpnumber [bpnumber ...]]

禁用断点作为空格分隔的断点号列表。禁用断点意​​味着它不能导致程序执行stopexecution,但与清除断点不同,它会保留在断点列表中并且可以(重新)启用.

enable [bpnumber [bpnumber ...]]

启用指定的断点.

ignore bpnumber [count]

设置给定断点号的忽略计数。如果省略count,则忽略计数设置为0.当ignorecount为零时,断点将变为活动状态。当非零时,每次到达断点并且断点未被禁用且任何关联条件的计算结果为真时,计数都会递减.

condition bpnumber [condition]

为断点设置一个新的condition,这个表达式必须是在断点被尊重之前评估为真。如果没有condition,则删除任何现有条件;即,断点是无条件的.

commands [bpnumber]

指定断点号bpnumber的命令列表。命令本身出现在以下几行。键入仅包含end的行以终止命令。例如:

(Pdb) commands 1(com) p some_variable(com) end(Pdb)

要从断点中删除所有命令,请键入commands并立即使用end;也就是说,不给任何命令.

没有bpnumber论证,commands指的是最后一个断点.

您可以使用断点命令重新启动程序。只需使用continue命令,或step,或任何其他恢复执行的命令.

指定任何恢复执行的命令(当前continue, step, next,return, jump, quit和它们的缩写)终止命令列表(好像该命令后面紧跟着结束)。这是因为任何时候你执行(即使是简单的下一步或步骤),你可能会遇到另一个断点 – 它可能有自己的命令列表,导致关于要执行哪个列表的歧义.

如果在命令列表中使用“silent”命令,则不会打印关于在断点处停止的常规消息。对于要打印特定消息然后继续的断点,这可能是合乎需要的。如果其他命令都没有打印任何内容,则看不到断点已到达的迹象.

s(tep)

执行当前行,在第一个可能的场合停止(在被调用的函数或当前函数的下一行).

n(ext)

继续执行,直到达到当前函数的下一行或返回。(nextstep之间的区别是step在一个被调用的函数内停止,而next以(几乎)全速执行被调用的函数,只停在当前函数的下一行。)

unt(il) [lineno]

如果没有参数,继续执行,直到达到当前数字的数字为止的行.

使用行号,继续执行直到有一行数量大于等于达到的数量。在这两种情况下,当当前帧返回时也会停止。

版本3.2中更改:允许给出明确的行号.

r(eturn)

继续执行直到当前函数返回.

c(ont(inue))

继续执行,只在遇到断点时停止.

j(ump) lineno

设置要执行的下一行。仅在最底层的框架中可用。这可以让你跳回来再次执行代码,或者跳转你不想运行的toskip代码.

应该注意的是,不是所有的跳跃都是允许的 – 例如,不可能跳到for循环的中间或finally条款之外

l(ist) [first[, last]]

列出当前文件的源代码。如果没有参数,请列出当前行的11行,或继续上一个列表。用.asargument,列出当前行周围的11行。使用一个参数,在该行列出11行。使用两个参数,列出给定范围;如果第二个参数小于第一个参数,则将其解释为count.

当前帧中的当前行由->表示。如果正在调试异常,则>>,如果它与当前行不同.

版本3.2: >> marker.

ll | longlist

列出当前函数或框架的所有源代码。有趣的线条标记为list.

版本3.2.

a(rgs)

中的新功能打印当前函数的参数列表.

p expression

在当前上下文中评估expression并打印其值.

注意

print()也可以使用,但不是调试器命令 – 这执行thePython print() function.

pp expression

p命令一样,除了使用表达式打印表达式的值pprint module.

whatis expression

打印expression.

source expression

的类型尝试获取给定对象的源代码并显示它.

新版本3.2.

display [expression]

如果表达式发生了变化,则每当执行停止在当前帧时显示表达式的值.

没有表达式,列出当前帧的所有显示表达式.

新版本3.2.

undisplay [expression]

不要在当前帧中再显示表达式。WithUtexpression,清除当前帧的所有显示表达式.

新版本3.2.

interact

启动一个交互式解释器(使用code模块),其globalnamespace包含在currentscope中找到的所有(全局和本地)名称.

新版本3.2.

alias [name [command]]

创建一个名为name别名,执行command。命令必须not用引号括起来。可更改的参数可以用%1, %2表示,依此类推,而%*被所有参数替换。如果没有给出命令,则显示name的当前别名。如果没有给出任何参数,则列出所有别名.

Aliases可以嵌套,并且可以包含任何可以在pdb提示符下合法输入的内容。请注意,内部pdb命令can将被byases重写。然后隐藏这样的命令,直到删除别名。Aliasingis递归地应用于命令行的第一个单词;该行中的所有其他单词都是单独存放的.

例如,这里有两个有用的别名(特别是当放在.pdbrc文件中时):

# Print instance variables (usage "pi classInst")alias pi for k in %1.__dict__.keys(): print("%1.",k,"=",%1.__dict__[k])# Print instance variables in selfalias ps pi self
unalias name

删除指定的别名

! statement

在当前堆栈帧的上下文中执行(单行)statement。除非语句的第一个单词包含调试器命令,否则可以省略感叹号。要设置一个全局变量,可以在同一行的前缀命令前加上global语句,例如:

(Pdb) global list_options; list_options = ["-l"](Pdb)
run [args ...]
restart [args ...]

重新启动调试的Python程序。如果提供了一个参数,它将与shlex一起拆分,并将结果用作新的sys.argv.History,断点,动作和调试器选项被保留.restart别名for run.

q(uit)

退出调试器。正在执行的程序被中止.

Footnotes

[1] 是否一个框架被认为是由某个模块发起的,由__name__确定框架全局.