pdb — Python 调试器
源代码: Lib/pdb.py
pdb模块为 Python 程序定义了一个交互式源代码调试器。它支持在源代码行级别设置(条件)断点和单步执行,检查堆栈框架,源代码列表以及在任何堆栈框架的上下文中评估任意 Python 代码。它还支持事后调试,可以在程序控制下调用。
调试器是可扩展的–实际上定义为类Pdb。目前尚无记录,但pass阅读源代码很容易理解。扩展接口使用模块bdb和cmd。
调试器的提示是(Pdb)
。在调试器的控制下运行程序的典型用法是:
>>> import pdb
>>> import mymodule
>>> pdb.run('mymodule.test()')
> <string>(0)?()
(Pdb) continue
> <string>(1)?()
(Pdb) continue
NameError: 'spam'
> <string>(1)?()
(Pdb)
在版本 3.3 中更改:passreadline模块完成制表符可用于命令和命令自变量,例如当前的全局名称和本地名称作为p
命令的参数提供。
pdb.py
也可以作为脚本调用来调试其他脚本。例如:
python3 -m pdb myscript.py
当作为脚本调用时,如果正在调试的程序异常退出,pdb 将自动进入事后调试。在事后调试之后(或在程序正常退出之后),pdb 将重新启动该程序。自动重启会保留 pdb 的状态(例如断点),并且在大多数情况下比在程序退出时退出调试器更为有用。
3.2 版中的新Function:pdb.py
现在接受-c
选项,该选项执行命令的方式就像.pdbrc
文件中给出的一样,请参见Debugger Commands。
3.7 版中的新Function:pdb.py
现在接受-m
选项,该选项执行与python3 -m
相似的模块。与脚本一样,调试器将在模块第一行之前暂停执行。
从正在运行的程序进入调试器的典型用法是插入
import pdb; pdb.set_trace()
在您想进入调试器的位置。然后,您可以单步执行此语句之后的代码,并使用continue命令在没有调试器的情况下 continue 运行。
3.7 版中的新Function:内置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)
该模块定义了以下Function;每个都以略有不同的方式进入调试器:
-
pdb.
run
(* statement , globals = None , locals = None *) -
pdb.
runeval
(* expression , globals = None , locals = None *) -
pdb.
runcall
(* function *, *args , * kwds *)- 使用给定的参数调用* function *(函数或方法对象,而不是字符串)。当runcall()返回时,它将返回所返回的函数调用。Importing Function后,调试器提示就会出现。
-
pdb.
set_trace
(**, header = None *)- 在调用堆栈帧处 Importing 调试器。即使没有对代码进行调试(例如,assert 失败时),这对于在程序中给定点硬编码断点也是很有用的。如果提供,* header *将在调试开始之前打印到控制台。
在版本 3.7 中更改:仅关键字参数* header *。
-
pdb.
post_mortem
(* traceback = None *)- Importing 给定* traceback 对象的事后调试。如果没有给出 traceback *,它将使用当前正在处理的异常之一(如果要使用默认值,则必须处理异常)。
-
pdb.
pm
( )- Importing 在sys.last_traceback中找到的回溯的事后调试。
run*
函数和set_trace()是用于实例化Pdb类并调用相同名称的方法的别名。如果要访问其他Function,则必须自己执行以下操作:
-
- class *
pdb.
Pdb
(* completekey ='tab', stdin = None , stdout = None , skip = None , nosigint = False , readrc = True *)
- Pdb是调试器类。
- class *
-
completekey , stdin 和 stdout *参数被传递给底层的cmd.Cmd类;看到那里的描述。
-
skip *参数(如果给定)必须是全局样式的模块名称模式的可迭代形式。调试器将不会进入源自与这些模式之一匹配的模块的框架。 [1]
默认情况下,当您发出continue
命令时,Pdb 会为 SIGINTsignal 设置处理程序(当用户在控制台上按 Ctrl-C 时发送)。这使您可以pass按 Ctrl-C 再次进入调试器。如果不希望 Pdb 触摸 SIGINT 处理程序,请将* nosigint *设置为 true。
- readrc *参数默认为 true,并控制 Pdb 是否从文件系统加载.pdbrc 文件。
使用* skip *启用跟踪的示例调用:
import pdb; pdb.Pdb(skip=['django.*']).set_trace()
引发不带参数的auditing event pdb.Pdb
。
3.1 版中的新Function:* skip *参数。
版本 3.2 中的新Function:* nosigint *参数。以前,Pdb 从未设置过 SIGINT 处理程序。
在版本 3.6 中更改:* readrc *参数。
run
((* statement , globals = None , locals = None *)runeval
(* expression , globals = None , locals = None *)runcall
(* function *, *args , * kwds *)set_trace
( )- 有关上述Function的信息,请参阅文档。
Debugger Commands
下面列出了调试器可以识别的命令。如所示,大多数命令可以缩写为一个或两个字母。例如h(elp)
表示可以使用h
或help
Importing 帮助命令(但不能 Importinghe
或hel
,也不能 ImportingH
或Help
或HELP
)。命令的参数必须用空格(空格或制表符)分隔。可选参数用命令语法括在方括号([]
)中;禁止 Importing 方括号。命令语法中的其他选项由竖线(|
)分隔。
Importing 空白行将重复最后 Importing 的命令。exception:如果最后一个命令是list命令,则会列出接下来的 11 行。
调试器无法识别的命令被假定为 Python 语句,并在被调试程序的上下文中执行。 Python 语句也可以带有感叹号(!
)作为前缀。这是检查正在调试的程序的强大方法。甚至可以更改变量或调用函数。当此类语句中发生异常时,将打印异常名称,但调试器的状态不会更改。
调试器支持aliases。别名可以具有允许对被检查的上下文有一定程度的适应性的参数。
可以在一行上 Importing 多个命令,并以;;
分隔。 (不使用单个;
,因为它是传递给 Python 解析器的一行中多个命令的分隔符.)没有智能可用于分隔命令。Importing 将在第一个;;
对处拆分,即使它在带引号的字符串中间。
如果用户的主目录或当前目录中存在文件.pdbrc
,则将其读入并执行,就像在调试器提示符下键入的一样。这对于别名特别有用。如果两个文件都存在,则首先读取主目录中的文件,并且本地文件可以覆盖其中定义的别名。
在版本 3.2 中更改:.pdbrc
现在可以包含 continue 调试的命令,例如continue或next。以前,这些命令无效。
-
h(elp)
[command]
- 不带参数的情况下,显示可用命令的列表。以* command 作为参数,打印关于该命令的帮助。
help pdb
显示完整的文档(pdb模块的文档字符串)。由于 command *参数必须是标识符,因此必须 Importinghelp exec
以获得有关!
命令的帮助。
- 不带参数的情况下,显示可用命令的列表。以* command 作为参数,打印关于该命令的帮助。
-
w(here)
- 打印堆栈跟踪,最新一帧在底部。箭头指示当前框架,该框架确定大多数命令的上下文。
-
d(own)
[count]
- 在堆栈跟踪中将当前帧* count *(默认值)向下移动一级(到新的帧)。
-
u(p)
[count]
- 在堆栈跟踪中将当前帧数* count *(默认值)向上移动(移至较旧的帧)。
-
b(reak)
[([filename:]lineno | function) [, condition]]
- 使用* lineno 参数,在当前文件中在那里设置一个分隔符。使用 function *参数,在该函数中的第一个可执行语句处设置一个break。行号可以以文件名和冒号作为前缀,以在另一个文件(可能是尚未加载的文件)中指定一个断点。在sys.path上搜索文件。请注意,每个断点都分配有一个编号,所有其他断点命令都引用该编号。
如果存在第二个参数,则该表达式必须在接受断点之前计算为 true。
不带参数的情况下,列出所有break,包括每个断点,命中该断点的次数,当前忽略计数以及关联的条件(如果有)。
-
tbreak
[([filename:]lineno | function) [, condition]]
- 临时断点,在第一次命中时会自动删除。参数与break相同。
-
cl(ear)
[filename:lineno | bpnumber [bpnumber ...]]
- 使用* filename:lineno *参数,清除此行上的所有断点。用空格分隔的断点列表,清除这些断点。不加 Arguments,清除所有break(但首先要求确认)。
-
disable
[bpnumber [bpnumber ...]]
- 禁用以空格分隔的断点编号列表形式给出的断点。禁用断点意味着它不会导致程序停止执行,但是与清除断点不同,它保留在断点列表中并且可以(重新)启用。
-
enable
[bpnumber [bpnumber ...]]
- 启用指定的断点。
-
ignore
bpnumber [count]
- 为给定的断点编号设置忽略计数。如果Ellipsis count,则忽略计数将设置为 0.当忽略计数为零时,断点将变为活动状态。如果为非零值,则每次达到断点时该计数都会递减,并且不会禁用该断点,并且任何关联条件的评估结果为 true。
-
condition
bpnumber [condition]
- 为断点设置一个新的“条件”,该表达式必须在接受断点之前求值为 true。如果* condition *不存在,则删除任何现有条件;即,将断点设为无条件。
-
commands
[bpnumber]
- 指定断点编号* bpnumber *的命令列表。命令本身出现在以下几行中。键入仅包含
end
的行以终止命令。一个例子:
- 指定断点编号* bpnumber *的命令列表。命令本身出现在以下几行中。键入仅包含
(Pdb) commands 1
(com) p some_variable
(com) end
(Pdb)
要从断点删除所有命令,请键入commands
并紧跟着end
;也就是说,不要给出任何命令。
没有* bpnumber *参数,commands
指向最后一个断点集。
您可以使用断点命令重新启动程序。只需使用continue命令或step或任何其他恢复执行的命令。
指定任何恢复执行的命令(当前为continue,step,next,return,jump,quit及其缩写)将终止命令列表(就像该命令紧随其后是结尾)。这是因为任何时候恢复执行(即使使用简单的下一步或步骤),都可能会遇到另一个断点,该断点可能具有自己的命令列表,从而导致执行哪个列表含糊不清。
如果在命令列表中使用“ silent”命令,则不会打印有关在断点处停止的常规消息。对于要打印特定消息然后 continue 的断点,这可能是理想的。如果没有其他命令可以打印任何内容,则看不到已达到断点的迹象。
-
s(tep)
- 执行当前行,在第一次可能的情况下停止(在调用的函数中或在当前函数的下一行中停止)。
-
n(ext)
-
unt(il)
[lineno]
- 不带参数的情况下,continue 执行,直到到达行号大于当前行的行为止。
使用行号,continue 执行,直到到达行号大于或等于该行的行为止。在这两种情况下,当当前帧返回时也要停止。
在版本 3.2 中更改:允许提供明确的行号。
-
r(eturn)
- continue 执行直到当前函数返回。
-
c(ont(inue))
- continue 执行,仅在遇到断点时停止。
-
j(ump)
lineno
- 设置将要执行的下一行。仅在最底部的框架中可用。这使您可以跳回并再次执行代码,或跳到跳过不想运行的代码。
应该注意的是,并非所有跳转都是允许的–例如,不可能跳转到for循环的中间或finally子句的中间。
l(ist)
[first[, last]]
- 列出当前文件的源代码。不带参数的情况下,在当前行周围列出 11 行,或 continue 上一个列表。以
.
作为参数,在当前行周围列出 11 行。使用一个参数,在该行周围列出 11 行。用两个参数列出给定的范围;如果第二个参数小于第一个参数,则将其解释为一个计数。
- 列出当前文件的源代码。不带参数的情况下,在当前行周围列出 11 行,或 continue 上一个列表。以
当前帧中的当前行由->
指示。如果正在调试异常,则该异常最初引发或传播的行由>>
指示,如果该行与当前行不同。
版本 3.2 中的新Function:>>
标记。
ll
| longlist
- 列出当前Function或框架的所有源代码。有趣的行被标记为list。
3.2 版中的新Function。
-
a(rgs)
- 打印当前函数的参数列表。
-
p
expression
- 在当前上下文中评估* expression *并打印其值。
Note
也可以使用print()
,但它不是调试器命令-执行 Python print()函数。
-
pp
expression
-
whatis
expression
- 打印* expression *的类型。
-
source
expression
- try获取给定对象的源代码并显示它。
3.2 版中的新Function。
display
[expression]
- 每次在当前帧中停止执行时,显示表达式的值(如果更改)。
如果不使用表达式,请列出当前帧的所有显示表达式。
3.2 版中的新Function。
undisplay
[expression]
- 在当前帧中不再显示该表达式。如果没有表达式,请清除当前帧的所有显示表达式。
3.2 版中的新Function。
interact
- 启动一个交互式解释器(使用code模块),该解释器的全局名称空间包含在当前作用域中找到的所有(全局和本地)名称。
3.2 版中的新Function。
alias
[name [command]]
- 创建一个名为* name 的别名,该别名执行 command 。该命令不得用引号引起来。可以用
%1
,%2
等表示可替换参数,而用所有参数替换%*
。如果未给出命令,则显示 name *的当前别名。如果未提供任何参数,则会列出所有别名。
- 创建一个名为* name 的别名,该别名执行 command 。该命令不得用引号引起来。可以用
别名可以嵌套,并且可以包含可以在 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
-
unalias
name
- 删除指定的别名。
-
!
statement
- 在当前堆栈框架的上下文中执行(单行)语句。除非语句的第一个单词类似于调试器命令,否则可以Ellipsis感叹号。要设置全局变量,您可以在赋值命令的前一行加上global语句,例如:
(Pdb) global list_options; list_options = ['-l']
(Pdb)
-
run
[args ...]
-
restart
[args ...]
-
q(uit)
- 从调试器退出。正在执行的程序被中止。
-
debug
code
- Importing 一个递归调试器,它逐步遍历 code 参数(这是要在当前环境中执行的任意表达式或语句)。
-
retval
- 打印函数的最后一次返回的返回值。
Footnotes
- [1]
- 帧是否被认为起源于某个模块由帧全局变量中的
__name__
确定。
- 帧是否被认为起源于某个模块由帧全局变量中的