27.3. pdb
- Python调试器¶
源代码: 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)
在版本3.3中更改:通过readline
模块完成标签可用于命令和命令参数,例如当前全局和局部名称作为p
命令的参数提供。
pdb.py
也可以作为脚本调用来调试其他脚本。例如:
python3 -m pdb myscript.py
当作为脚本调用时,如果正在调试的程序异常退出,pdb将自动进入事后调试。经过死后调试(或正常退出程序后),pdb将重新启动程序。自动重新启动保留pdb的状态(例如断点),并且在大多数情况下比程序退出时退出调试器更有用。
New in version 3.2: pdb.py
now accepts a -c
option that executes commands as if given in a .pdbrc
file, see Debugger Commands.
从正在运行的程序中断入调试器的典型用法是插入
import pdb; pdb.set_trace()
在您想要打破调试器的位置。然后,您可以按照此语句逐步执行代码,并使用continue
命令继续运行,而不使用调试器。
检查崩溃程序的典型用法是:
>>> import pdb
>>> import mymodule
>>> mymodule.test()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
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=None, locals=None)¶ 在调试器控制下执行语句(作为字符串或代码对象)。在任何代码执行之前出现调试器提示;您可以设置断点并键入
continue
,也可以使用step
或next
逐步执行该语句(所有这些命令将在下面说明)。可选的全局变量和局部变量参数指定执行代码的环境;默认使用模块的字典__main__
。(请参阅内建exec()
或eval()
函数的解释。)
-
pdb.
runeval
(expression, globals=None, locals=None)¶ 在调试器控制下计算表达式(作为字符串或代码对象)。当
runeval()
返回时,它返回表达式的值。否则,此函数类似于run()
。
-
pdb.
runcall
(function, *args, **kwds)¶ 使用给定的参数调用函数(函数或方法对象,而不是字符串)。当
runcall()
返回时,它返回所返回的任何函数调用。一旦输入该函数,就会显示调试器提示。
-
pdb.
set_trace
()¶ 在调用堆栈框架处输入调试器。这对于在程序中的给定点硬编码断点是有用的,即使代码没有被另外调试(例如,当断言失败时)。
-
pdb.
post_mortem
(traceback=None)¶ 输入给定traceback对象的事后调试。如果未给出traceback,则使用当前正在处理的异常(如果使用缺省值,则必须处理异常)。
-
pdb.
pm
()¶ 输入在
sys.last_traceback
中找到的回溯的事后调试。
run*
函数和set_trace()
是用于实例化Pdb
类和调用同名方法的别名。如果你想访问更多的功能,你必须自己这样做:
- class
pdb.
Pdb
(completekey='tab', stdin=None, stdout=None, skip=None, nosigint=False)¶ Pdb
是调试器类。completekey,stdin和stdout参数传递给底层的
cmd.Cmd
看到那里的描述。如果给定了skip参数,则必须是可重复的glob样式模块名称模式。调试器不会步入到源于与这些模式之一匹配的模块中的帧。[1]
默认情况下,当您给出
continue
命令时,Pdb会为SIGINT信号设置处理程序(当用户在控制台上按Ctrl-C
时发送)。这允许您通过按Ctrl-C
再次进入调试器。如果要让Pdb不触摸SIGINT处理程序,请将nosigint设置为true。使用skip启用跟踪的示例调用:
import pdb; pdb.Pdb(skip=['django.*']).set_trace()
版本3.1中的新功能: 跳过参数。
版本3.2中的新功能: nosigint参数。以前,一个SIGINT处理程序从来没有被Pdb设置。
27.3.1. Debugger Commands¶
调试器识别的命令如下所示。大多数命令可以缩写为一个或两个字母,如图所示;例如h(elp)
means that either h
or help
can be used to enter the help command (but not he
or hel
, nor H
or Help
or HELP
). 命令的参数必须由空格(空格或制表符)分隔。可选参数在命令语法中用方括号([]
)括起来;不得输入方括号。命令语法中的其他选项通过垂直条(|
)分隔。
输入空行重复输入的最后一个命令。异常:如果最后一个命令是list
命令,则会列出接下来的11行。
调试器不能识别的命令假定为Python语句,并在正在调试的程序的上下文中执行。Python语句也可以带有感叹号(!
)作为前缀。这是一种检查被调试程序的有效方法;甚至可以改变变量或调用函数。当在此类语句中发生异常时,将打印异常名称,但调试器的状态不会更改。
调试器支持aliases。别名可以具有允许对检查的上下文具有一定水平的适应性的参数。
多个命令可以在单行上输入,由;;
分隔。(不使用单个;
,因为它是传递给Python解析器的行中的多个命令的分隔符。)没有智能用于分离命令;输入在第一个;;
对处拆分,即使它位于带引号的字符串的中间。
如果文件.pdbrc
存在于用户的主目录或当前目录中,则会读入该文件并执行,就好像它在调试器提示符处键入。这对别名特别有用。如果两个文件都存在,那么首先读取主目录中的一个文件,并在那里定义的别名可以被本地文件覆盖。
-
h(elp)
[command]
¶ 无参数时,打印可用命令的列表。使用命令作为参数,打印有关该命令的帮助。
help pdb
显示完整文档(pdb
模块的文档字符串)。Since the command argument must be an identifier,help exec
must be entered to get help on the!
命令。
-
w(here)
¶ 打印堆栈跟踪,最新的帧在底部。箭头表示当前帧,它确定大多数命令的上下文。
-
d(own)
[count]
¶ 将当前帧计数(默认一个)向下移动到堆栈跟踪(更新的帧)。
-
u(p)
[count]
¶ 将当前帧计数(默认值)移动到堆栈跟踪(到较早的帧)。
-
b(reak)
[([filename:]lineno | function) [, condition]]
¶ 使用lineno参数,在当前文件中设置断点。使用函数参数,在该函数中的第一个可执行语句中设置断点。行号可以用文件名和冒号作为前缀,以在另一个文件(可能是尚未加载的文件)中指定断点。在
sys.path
上搜索文件。请注意,每个断点都分配有一个数字,所有其他断点命令都引用该数字。如果存在第二个参数,它是一个表达式,在断点被执行之前必须计算为true。
无参数,列出所有中断,包括每个断点,断点被命中的次数,当前忽略计数和相关条件(如果有)。
-
cl(ear)
[filename:lineno | bpnumber [bpnumber ...]]
¶ 使用filename:lineno参数,清除此行的所有断点。用断点号的空格分隔列表,清除那些断点。没有论证,清除所有休息(但首先要求确认)。
-
disable
[bpnumber [bpnumber ...]]
¶ 禁用以空格分隔的断点号列表形式给出的断点。禁用断点意味着它不能导致程序停止执行,但是与清除断点不同,它保留在断点列表中,并且可以(重新)启用。
-
enable
[bpnumber [bpnumber ...]]
¶ 启用指定的断点。
-
ignore
bpnumber [count]
¶ 设置给定断点号的忽略计数。如果省略count,则忽略计数设置为0。当忽略计数为零时,断点变为活动状态。当非零时,每次达到断点时计数递减,并且不禁用断点,并且任何关联条件的计算结果为true。
-
condition
bpnumber [condition]
¶ 为断点设置新的条件,这是在断点被执行之前必须计算为true的表达式。如果条件不存在,则删除任何现有条件;即断点是无条件的。
-
commands
[bpnumber]
¶ 指定断点号bpnumber的命令列表。命令本身显示在以下行。键入仅包含
end
的行以终止命令。一个例子:(Pdb) commands 1 (com) p some_variable (com) end (Pdb)
要从断点中删除所有命令,请键入命令,并立即使用
end
;即,不给出命令。没有bpnumber参数,命令引用最后一个断点集。
您可以使用断点命令重新启动程序。只需使用continue命令,或step,或任何其他恢复执行的命令。
指定任何恢复执行的命令(当前继续,步骤,下一步,返回,跳转,退出和它们的缩写)终止命令列表(就好像该命令紧接着结束)。这是因为任何时候你恢复执行(即使有一个简单的下一步或步骤),你可能会遇到另一个断点,这可能有自己的命令列表,导致执行列表的模糊。
如果在命令列表中使用“silent”命令,则不会打印关于在断点处停止的常见消息。这对于打印特定消息然后继续的断点可能是合乎需要的。如果没有其他命令打印任何东西,您看不到到达断点的迹象。
-
s(tep)
¶ 执行当前行,在第一个可能的时间停止(在调用的函数中或当前函数中的下一行)。
-
unt(il)
[lineno]
¶ 如果没有参数,继续执行直到到达具有大于当前数字的数字的行。
使用行号,继续执行,直到到达具有大于或等于的数字的行。在这两种情况下,当当前帧返回时也停止。
在版本3.2中更改:允许给出明确的行号。
-
r(eturn)
¶ 继续执行直到当前函数返回。
-
c(ont(inue))
¶ 继续执行,只有在遇到断点时停止。
-
j(ump)
lineno
¶ 设置将要执行的下一行。仅在最下面的框架中可用。这允许您跳回并再次执行代码,或者向前跳转以跳过您不想运行的代码。
-
l(ist)
[first[, last]]
¶ 列出当前文件的源代码。如果没有参数,请列出当前行周围的11行或继续上一个列表。使用
.
作为参数,列出当前行周围的11行。使用一个参数,在该行列出11行。有两个参数,列出给定的范围;如果第二个参数小于第一个,它将被解释为计数。当前帧中的当前行由
->
指示。如果正在调试异常,则异常最初提出或传播的行由>>
指示,如果它与当前行不同。版本3.2中的新功能:
>>
标记。
-
a(rgs)
¶ 打印当前函数的参数列表。
-
whatis
expression
¶ 打印表达式的类型。
-
source
expression
¶ 尝试获取给定对象的源代码并显示它。
版本3.2中的新功能。
-
display
[expression]
¶ 如果表达式更改,则每次在当前帧中停止执行时,显示表达式的值。
不带表达式时,列出当前帧的所有显示表达式。
版本3.2中的新功能。
-
undisplay
[expression]
¶ 不要在当前框架中再显示表达式。如果没有表达式,请清除当前框架的所有显示表达式。
版本3.2中的新功能。
-
alias
[name [command]]
¶ 创建一个名为name的执行命令的别名。The command must not be enclosed in quotes. 可替换参数可由
%1
,%2
等指示,而%*
由所有参数替换。如果未给出命令,则会显示名称的当前别名。如果没有给出参数,则列出所有别名。别名可以嵌套,并且可以包含可以在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
¶在当前堆栈帧的上下文中执行(一行)语句。可以省略感叹号,除非语句的第一个单词类似于调试器命令。要设置全局变量,您可以在同一行上使用
global
语句为赋值命令添加前缀,例如。:(Pdb) global list_options; list_options = ['-l'] (Pdb)
-
run
[args ...]
¶ -
restart
[args ...]
¶ 重新启动调试的Python程序。如果提供了参数,则使用
shlex
进行分割,并将结果用作新的sys.argv
。历史,断点,动作和调试器选项被保留。restart
是run
的别名。
-
q(uit)
¶ 从调试器中退出。正在执行的程序中止。
脚注
[1] | 帧是否被认为源于某个模块由帧全局中的__name__ 确定。 |