26.2. pdb — Python 调试器 — Python 文档
26.2. 数据库 — Python 调试器
源代码: :source:`Lib/pdb.py`
模块 pdb 为 Python 程序定义了一个交互式源代码调试器。 它支持在源代码行级别设置(条件)断点和单步执行、检查堆栈帧、源代码列表以及在任何堆栈帧的上下文中评估任意 Python 代码。 它还支持事后调试,可以在程序控制下调用。
调试器是可扩展的——它实际上被定义为类 Pdb。 这目前没有记录,但通过阅读源代码很容易理解。 扩展接口使用模块 bdb 和 cmd。
调试器的提示是 (Pdb)
。 在调试器控制下运行程序的典型用法是:
>>> import pdb
>>> import mymodule
>>> pdb.run('mymodule.test()')
> <string>(0)?()
(Pdb) continue
> <string>(1)?()
(Pdb) continue
NameError: 'spam'
> <string>(1)?()
(Pdb)
pdb.py
也可以作为脚本调用来调试其他脚本。 例如:
python -m pdb myscript.py
当作为脚本调用时,如果被调试的程序异常退出,pdb会自动进入事后调试。 事后调试后(或程序正常退出后),pdb 将重新启动程序。 自动重新启动会保留 pdb 的状态(例如断点),并且在大多数情况下比在程序退出时退出调试器更有用。
2.4 版新功能: 添加了重新启动验尸行为。
从正在运行的程序中进入调试器的典型用法是插入
import pdb; pdb.set_trace()
在您想要进入调试器的位置。 然后,您可以单步执行此语句后的代码,并使用 c
命令在没有调试器的情况下继续运行。
检查崩溃程序的典型用法是:
>>> 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.run(statement[, globals[, locals]])
- 在调试器控制下执行 语句 (以字符串形式给出)。 在执行任何代码之前会出现调试器提示; 您可以设置断点并键入
continue
,或者您可以使用step
或next
单步执行语句(所有这些命令都在下面解释)。 可选的 globals 和 locals 参数指定执行代码的环境; 默认情况下使用模块 __main__ 的字典。 (参见 exec 语句或 eval() 内置函数的解释。)
- pdb.runeval(expression[, globals[, locals]])
- 在调试器控制下计算 表达式 (以字符串形式给出)。 当 runeval() 返回时,它返回表达式的值。 否则这个函数类似于 run()。
- pdb.runcall(function[, argument, ...])
- 使用给定的参数调用 函数 (函数或方法对象,而不是字符串)。 当 runcall() 返回时,它返回函数调用返回的任何内容。 一旦输入函数,调试器提示就会出现。
- pdb.set_trace()
- 在调用堆栈帧处进入调试器。 这对于在程序中的给定点硬编码断点很有用,即使代码没有被调试(例如 当断言失败时)。
- pdb.post_mortem([traceback])
- 进入给定的 traceback 对象的事后调试。 如果没有给出 traceback,它使用当前正在处理的异常之一(如果要使用默认值,则必须处理异常)。
- pdb.pm()
- 进入在 sys.last_traceback 中找到的回溯的事后调试。
run*
函数和set_trace()是实例化Pdb类并调用同名方法的别名。 如果您想访问更多功能,您必须自己执行此操作:
- class pdb.Pdb(completekey='tab', stdin=None, stdout=None, skip=None)
Pdb 是调试器类。
completekey、stdin 和 stdout 参数被传递给底层的 cmd.Cmd 类; 请参阅那里的说明。
skip 参数(如果给定)必须是全局样式模块名称模式的可迭代对象。 调试器不会进入源自与这些模式之一匹配的模块的帧。 1
使用 skip 启用跟踪的示例调用:
import pdb; pdb.Pdb(skip=['django.*']).set_trace()
2.7 版新功能:skip 参数。
- run(statement[, globals[, locals]])
runeval(expression[, globals[, locals]])
runcall(function[, argument, ...])
set_trace() 有关上述功能,请参阅文档。
- run(statement[, globals[, locals]])
26.3. 调试器命令
调试器识别以下命令。 大多数命令可以缩写为一两个字母; 例如 h(elp)
表示可以使用 h
或 help
输入帮助命令(但不能使用 he
或 hel
,也不能使用 H
或 Help
或 HELP
)。 命令的参数必须用空格(空格或制表符)分隔。 可选参数在命令语法中括在方括号 ([]
) 中; 不得键入方括号。 命令语法中的替代项由竖线 (|
) 分隔。
输入一个空行会重复输入的最后一个命令。 例外:如果最后一个命令是 list
命令,则列出接下来的 11 行。
调试器无法识别的命令被假定为 Python 语句,并在被调试程序的上下文中执行。 Python 语句也可以带有感叹号前缀 (!
)。 这是检查正在调试的程序的有效方法; 甚至可以更改变量或调用函数。 当在这样的语句中发生异常时,会打印异常名称,但不会更改调试器的状态。
可以在一行中输入多个命令,用 ;;
分隔。 (不使用单个 ;
,因为它是传递给 Python 解析器的一行中多个命令的分隔符。)没有应用智能来分隔命令; 输入在第一个 ;;
对处拆分,即使它位于带引号的字符串的中间。
调试器支持别名。 别名可以具有允许对所检查的上下文具有一定程度的适应性的参数。
如果文件 .pdbrc
存在于用户的主目录或当前目录中,则它会被读入并执行,就像在调试器提示符下键入一样。 这对于别名特别有用。 如果两个文件都存在,则首先读取主目录中的文件,并且本地文件可以覆盖在那里定义的别名。
- h(elp) [命令]
不带参数,打印可用命令列表。 使用 command 作为参数,打印有关该命令的帮助。
help pdb
显示完整的文档文件; 如果定义了环境变量PAGER
,则文件将通过该命令进行管道传输。 由于 command 参数必须是标识符,因此必须输入help exec
以获取有关!
命令的帮助。- 在哪里)
打印堆栈跟踪,最新的帧在底部。 箭头指示当前帧,它决定了大多数命令的上下文。
- 下)
将当前帧在堆栈跟踪中向下移动一级(到更新的帧)。
- 向上)
在堆栈跟踪中将当前帧向上移动一级(到较旧的帧)。
- b(reak) [[filename:]lineno | 功能[, 条件]]
使用 lineno 参数,在当前文件中设置一个中断。 使用 function 参数,在该函数内的第一个可执行语句处设置中断。 行号可能以文件名和冒号为前缀,以指定另一个文件(可能尚未加载的文件)中的断点。 在
sys.path
上搜索文件。 请注意,每个断点都分配了一个编号,所有其他断点命令都引用该编号。如果存在第二个参数,则它是一个表达式,该表达式必须在断点生效之前计算为真。
不带参数,列出所有中断,包括每个断点、该断点被击中的次数、当前忽略计数以及相关条件(如果有)。
- tbreak [[filename:]lineno | 功能[, 条件]]
临时断点,第一次命中时自动移除。 参数与 break 相同。
- cl(ear) [filename:lineno | bpnumber [bpnumber …]]
使用 filename:lineno 参数,清除该行的所有断点。 使用空格分隔的断点编号列表,清除这些断点。 没有争论,清除所有中断(但首先要求确认)。
- 禁用 [bpnumber [bpnumber …]]
禁用以空格分隔的断点编号列表给出的断点。 禁用断点意味着它不会导致程序停止执行,但与清除断点不同,它保留在断点列表中并且可以(重新)启用。
- 启用 [bpnumber [bpnumber …]]
启用指定的断点。
- 忽略 bpnumber [count]
设置给定断点编号的忽略计数。 如果省略计数,则忽略计数设置为 0。 当忽略计数为零时,断点变为活动状态。 如果非零,则每次到达断点时计数都会递减,并且不会禁用断点,并且任何关联的条件评估为真。
- 条件bpnumber[条件]
条件是一个表达式,它必须在断点被遵守之前评估为真。 如果条件不存在,则删除任何现有条件; 即,断点是无条件的。
- 命令 [bpnumber]
为断点编号 bpnumber 指定命令列表。 命令本身出现在以下几行中。 键入仅包含“end”的行以终止命令。 一个例子:
(Pdb) commands 1 (com) print some_variable (com) end (Pdb)
要从断点中删除所有命令,请键入命令并紧随其后加上 end; 也就是说,不发出任何命令。
如果没有 bpnumber 参数,命令将引用最后一个断点集。
您可以使用断点命令再次启动您的程序。 只需使用 continue 命令、步骤或任何其他恢复执行的命令。
指定恢复执行的任何命令(当前 continue、step、next、return、jump、quit 及其缩写)将终止命令列表(就好像该命令紧跟在 end 之后)。 这是因为任何时候您恢复执行(即使是简单的下一步或步骤),您都可能遇到另一个断点——它可能有自己的命令列表,导致关于执行哪个列表的歧义。
如果您在命令列表中使用“silent”命令,则不会打印有关在断点处停止的常见消息。 对于要打印特定消息然后继续的断点,这可能是可取的。 如果其他命令都没有打印任何内容,您就看不到到达断点的迹象。
2.5 版中的新功能。
- 步)
执行当前行,在第一个可能的情况下停止(在被调用的函数中或在当前函数的下一行)。
- 下一个)
继续执行,直到到达当前函数的下一行或返回。 (
next
和step
的区别在于step
在被调用函数内停止,而next
以(几乎)全速执行被调用函数,仅停止在当前函数的下一行。)- 直到)
继续执行,直到到达行号大于当前行的行或从当前帧返回时。
2.6 版中的新功能。
- 返回)
继续执行直到当前函数返回。
- 继续))
继续执行,只在遇到断点时停止。
- j(ump) lineno
设置将要执行的下一行。 仅在最底部的框架中可用。 这使您可以跳回并再次执行代码,或向前跳以跳过不想运行的代码。
- l(ist) [first[, last]]
列出当前文件的源代码。 不带参数,在当前行周围列出 11 行或继续上一个列表。 使用一个参数,在该行周围列出 11 行。 使用两个参数,列出给定的范围; 如果第二个参数小于第一个参数,则将其解释为计数。
- a(rgs)
打印当前函数的参数列表。
- p 表达式
在当前上下文中计算 表达式 并打印其值。
笔记
print
也可以使用,但不是调试器命令——它执行 Python print 语句。- pp 表达式
类似于
p
命令,除了表达式的值是使用 pprint 模块漂亮打印的。- 别名 [ 名称 [命令]]
创建一个名为 name 的别名,用于执行 command。 命令必须用 not 括在引号中。 可替换的参数可以用
%1
、%2
等表示,而%*
则表示为所有参数。 如果未给出命令,则显示 name 的当前别名。 如果没有给出参数,则列出所有别名。别名可以嵌套并且可以包含可以在 pdb 提示符下合法键入的任何内容。 请注意,内部 pdb 命令 可以 被别名覆盖。 然后隐藏这样的命令,直到删除别名。 别名递归地应用于命令行的第一个单词; 该行中的所有其他单词都单独保留。
例如,这里有两个有用的别名(尤其是放在
.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 self alias ps pi self
- 取消别名 名称
删除指定的别名。
- [!]声明
在当前堆栈帧的上下文中执行(一行)语句。 感叹号可以省略,除非语句的第一个单词类似于调试器命令。 要设置全局变量,您可以在同一行中使用
global
命令作为赋值命令的前缀,例如:(Pdb) global list_options; list_options = ['-l'] (Pdb)
- 运行 [args …]
重新启动已调试的 Python 程序。 如果提供了一个参数,它会被“shlex”分割,结果被用作新的 sys.argv。 历史记录、断点、操作和调试器选项被保留。 “重启”是“运行”的别名。
2.6 版中的新功能。
- 辞职)
退出调试器。 正在执行的程序被中止。
脚注
- 1
- 帧是否被认为源自某个模块由帧全局变量中的
__name__
决定。