使用pdb进行条件断点调试

26

听起来我错过了极其简单的事情,我正在尝试使用以下代码在我的Python代码中设置断点:

if(some condition):
        pdb.set_trace()

在大量迭代后,我的代码出现了错误…难以使用print等方法进行调试。当条件触发时,我能够打印内容,但我想设置断点。

--编辑--

实际代码:

import pdb
if (node_num == 16):
    print node_num
    pdb.set_trace()

是的,你所做的应该有效,如果你在那个作用域中有可以访问的某种计数器,你可以简单地使用 if count > limit:,然后执行流将进入该块,触发 set_trace 并且执行将会在那里暂停。 - metatoaster
我刚刚尝试了一些非常简单的东西: 如果(条件): 打印“” pdb.set_trace() ##########打印出现了,但断点没有出现!! - sanjay
你是否已经导入了pdb?尝试使用import pdb;pdb.set_trace() - metatoaster
是的,我能够在 if 条件之外使用 pdb.set_trace()……是的,已经导入了 pdb。 - sanjay
你能否更新你的问题,将完整代码与循环开始、打印语句和调用 pdb.set_trace() 都包含进去? - metatoaster
这有帮助吗?代码太大了,无法在此处发布。 - sanjay
3个回答

56

我看到你找到了解决方案,Sanjay。但对于那些来到这里寻找使用pdb设置条件断点的方法的人:

不要像硬编码条件一样,例如if node_num == 16:,而是在交互模式下运行pdb。示例代码:

import pdb

for node_num in range(50):
  do_something(node_num)
...

在shell中使用-m pdb启动调试模式的脚本:

[rick@rolled ~]$ python -m pdb abc.py
> /home/dcadm/abc.py(1)<module>()
-> import pdb
(Pdb) l
  1  -> import pdb
  2
  3     for node_num in range(50) :
  4       foo = 2**node_num
[EOF]
(Pdb) b 4, node_num > 4
Breakpoint 1 at /home/dcadm/abc.py:4
(Pdb) c
> /home/dcadm/abc.py(4)<module>()
-> foo = 2**node_num
(Pdb) node_num 
5
(Pdb)

当node_num大于4时,b 4, node_num > 4命令会在第4行中断。


谢谢你提供这个好的解决方案。你知道在 pudb 中是否有类似的方法可以使用吗? - Sinooshka

16
为了在pdb中实际使用条件断点,你可以按照以下步骤进行:

b(reak) [([文件名:]行号 | 函数名) [, 条件]]

https://docs.python.org/zh-cn/3/library/pdb.html#pdbcommand-break

例如我正在运行一些测试代码来迭代django视图。我只想在到达我感兴趣的特定视图时暂停执行:

b C:\Users\powlo\project\tests\TestCase.py:350, view.view_name == 'app.views.export'


2

我不确定为什么你的代码不能正常工作,但是你可以在本地机器上创建一个新文件,以查看是否可以实现你想要做的事情。

import pdb

for node_num in range(50):
    if node_num == 16:
        print(node_num)
        pdb.set_trace()

现在要运行它:

16
> /tmp/tmp.py(3)<module>()
-> for node_num in range(50):
(Pdb) p node_num
16

如您所见,这个简单的例子已经按预期工作,现在需要您想办法将其适应到您的代码中,或者找出是什么其他问题导致了提示未显示。

另外,如果您有一个在异常中停止运行的函数,并且想要知道导致异常的确切行,请使用post_mortem。将有问题的代码部分用此方法包装起来即可。

try:
    problem_function()
except Exception:  # or the specific exception type thrown
    pdb.post_mortem()
    raise

post_mortem的作用是在异常发生的那个堆栈帧上设置一个断点,这样可以检查所有的值,然后让您继续执行。但是我还在结尾处放置了一个raise,以允许异常像正常情况一样继续执行,这意味着程序不会从异常发生的地方重新开始执行,而只是暂停在异常处理块中,因为有了post_mortem调用。在检查出问题后就可以放弃了。


@metatoaster..非常感谢你的回复,我尝试了很多不同的方法来调试这个问题,但最终看起来是因为我超过了最大递归深度。通过添加以下代码解决了这个问题:sys.setrecursionlimit(10000)这就是我不能设置断点的原因...我最初以为这与我的编译器有关,但当我重新验证了编译器等内容后,我发现这就是问题所在。 我从来没有想过我应该搜索一下最大递归深度。 - sanjay
抱歉耽搁了,由于怀疑编译器出现故障,我将我的代码移动到另一台我有权限的服务器上。 - sanjay
我只是从上周开始使用Python(通常使用Perl、C++、C等)……这肯定是我见过的最奇怪的错误。 - sanjay
@sanjay 哦,是的,如果你告诉我实际的异常,我会告诉你做其他事情。我刚刚编辑了这里的答案以反映这一点。 - metatoaster
1
哦,还有这并不像看起来那么奇怪。Python默认情况下没有尾递归,因此这个限制是为了防止堆栈溢出 - https://dev59.com/X3A75IYBdhLWcg3wYYBQ - metatoaster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接