Python中的pdb/ipdb如何在可编辑条件下中断程序?

25

假设我有以下代码:

for i in range(100):
    print i

一般情况下,我可以在代码中添加一行:

for i in range(100):
    import ipdb;ipdb.set_trace()
    print i

然而,现在我想在条件 i == 10 下进行调试,而且我不想在 ipdb 中打十次 c,我该怎么做?

在文档中,我找到了 condition bpnumber [condition],但如果没有 bpnumber 索引列表,我怎么知道 bpnumber 是什么。文档还说 b(reak) ([file:]lineno | function) [, condition]。例如,假设 print i 的行号是 xx。我在 ipdb shell 中输入了以下内容:b xx, i == 10,但并没有像预期的那样发生任何事情。

3个回答

28

我自己进行了一些探索,以下是我对 pdb 的新理解。

当你输入 import ipdb;ipdb.set_trace() 时,实际上是在该行添加了一个 ipdb的入口点,而不是真正的断点。

进入 ipdb 后,您可以设置断点。

因此,要实现我想要的条件调试,我应该这样做:

import ipdb;ipdb.set_trace()
for i in range(100):
    print i

然后我输入 ipdb 后,我可以输入 b xx, i == 10,然后输入 cr 来运行代码。当条件满足时,代码将停止。

当我输入 l 时,该行的 bpnumber 显示为:

          xx-1                  for i in range(100): 
bpnumber> xx                        print i
          xx+1                      ...

我不得不说,这份文件和所有其他解释都非常混乱,我希望我的回答能够澄清“调试入口点”和“调试断点”之间的区别。


@Rugnar xx 表示左侧显示的行号。 - chener

12

有一种快速而粗糙的方法,像这样:

for i in range(100):
    if i == 10: import ipdb;ipdb.set_trace()
    print i

它有效,并且您不必费心使用任何其他命令:)


2
好的,我同意,但这对代码来说太过侵入性了,如果我想改变条件,就不得不时常更改代码。 - shelper
1
好的,但是想一想,我编辑了我的代码,将它留在了只有一行的代码中。你不认为这和 import pdb;ipdb.set_trace() 一样具有侵入性吗?虽然我同意使用 condition 是有用的,但我似乎找不到任何关于如何使用它的参考资料。 - Paulo Bu
2
假设您已经在pdb中,对于i==10您找不到任何问题,但是您想尝试i==50,如果您无法设置条件断点,则必须退出pdb,修改代码为if i==50:,然后再次运行。这并不是用户友好的...无论如何,感谢您的建议。 - shelper

11
我认为您正在寻找一种更直接的解决方案,而不是在代码中添加行,并且只涉及调试器命令。
您最初的示例是:
b xx, i == 10 

由于您在代码中插入了ipdb.set_trace()命令并在该位置设置断点,因此无法正常工作。通过在调试器中添加语句“b xx, i==10”,您实际上在同一位置定义了2个断点(1个有条件的和1个无条件的),其中xx是set_trace()命令所在的行号。

或者,一旦使用“b”命令在代码中定义了断点(显然这对您有效),您可以通过添加条件来设置断点。

condition bpnumber boolean-expression

例如

condition 1 i == 10
注意:bpnumber是分配给断点的编号,而不是您代码中的行号。要查看断点列表,只需输入“ b”而不带任何参数即可。
此外,如果您想在不使用ipdb.set_trace()的情况下进入调试模式,只需启用pdb/ipbd模块并运行代码即可。
python -m pdb foo.py

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