如何在Python PDB中继续到下一个循环迭代?

8

给定以下示例代码:

import pdb

for i in range(10):
  pdb.set_trace()
  print(str(i))

当我从PDB得到提示时,如何使用continue循环控制语句跳过循环中的一次迭代,而不与PDB一起使用,以继续代码执行?

当我从PDB得到提示时,如果要跳过循环中的一次迭代,并且在使用PDB继续代码执行时不想与之产生冲突,可以使用continue循环控制语句。

所以,明确一下,您希望代码的行为就像执行了一个 continue 语句一样?您不希望在该循环中打印 str(i),对吗? - Kevin
1
顺便提一下,“如何区分pdb命令和只是看起来像pdb命令的Python表达式”的一般问题,您可以在Python表达式前加上感叹号。但这似乎不适用于特定的“continue”命令。 - Kevin
如果在循环末尾添加一个pass语句,您就可以跳转到循环的结尾,然后继续执行,下一次迭代循环将被正确初始化。 - Dunes
谢谢大家!我也感谢Kevin的评论,这是一种确认,只能通过解决方法来完成。 - Andor
@Dunes:当我意识到向前跳转的唯一方法是有一些在被跳过的语句之后时,我也想到了同样的想法。我看到你编辑和取消删除后发布了相同的内容,对此感到抱歉。 - Martijn Pieters
@MartijnPieters,我在撰写自己的答案时看到你的答案被发布并删除。我想让你知道,因为你随后评论说这是不可能的。无论如何,我认为你的答案更好,因为它更全面和详细。 - Dunes
2个回答

9
你无法使用continue,因为调试器中的新语句需要在没有其他上下文的情况下是完整和有效的;只有在编译时被放在循环结构内部时才能使用continue。因此,即使调试器正在处理循环结构,也不能使用!continue(使用可以防止pdb解释该命令)。
你可以使用j[ump]命令,前提是有一个更晚的语句要跳转到。如果你的循环在你想跳过的语句之后为空,你只能"倒带"。
$ bin/python test.py
> /.../test.py(5)<module>()
-> print(str(i))
(Pdb) l
  1     import pdb
  2     
  3     for i in range(10):
  4         pdb.set_trace()
  5  ->     print(str(i))
  6     
[EOF]
(Pdb) j 3
> /.../test.py(3)<module>()
-> for i in range(10):

j 3 跳转到第三行,没有跳过任何内容; 第三行将被重新执行,包括设置 range()。你可以跳到第四行,但是这个 for 循环不会前进。

你需要在循环结束时添加另一个语句,以便跳转到 Python 继续执行。该语句可以是 print()pass 或任何不必改变状态的东西。你甚至可以使用 continue 作为最后一条语句。我使用了 i:

for i in range(10):
    pdb.set_trace()
    print(str(i))
    i  # only here to jump to.

示例:

$ bin/python test.py
> /.../test.py(5)<module>()
-> print(str(i))
(Pdb) l
  1     import pdb
  2     
  3     for i in range(10):
  4         pdb.set_trace()
  5  ->     print(str(i))
  6         i  # only here to jump to.
  7     
[EOF]
(Pdb) j 6
> /.../test.py(6)<module>()
-> i  # only here to jump to.
(Pdb) c
> /.../test.py(4)<module>()
-> pdb.set_trace()
(Pdb) s
> /.../test.py(5)<module>()
-> print(str(i))
(Pdb) j 6
> /.../test.py(6)<module>()
-> i  # only here to jump to.
(Pdb) i
1
(Pdb) c
> /.../test.py(4)<module>()
-> pdb.set_trace()
(Pdb) s
> /.../test.py(5)<module>()
-> print(str(i))
(Pdb) j 6
> /.../test.py(6)<module>()
-> i  # only here to jump to.
(Pdb) i
2

来自调试器命令

j(ump) 行号
设置将要执行的下一行。只在最底层的框架中可用。这使您可以跳回并重新执行代码,或跳过不想运行的代码。

值得注意的是,并非所有的跳转都被允许——例如,不能跳入一个for循环的中间或跳出finally子句。


“j[ump]”不会跳过执行代码直到“jump target”吗?我错过了什么吗? - 0xc0de
@0xc0de continue 跳过执行循环的剩余部分,这正是你在这里所需要的。然而,跳转到 for 行会重新启动循环,因此并不完全相同。在循环体末尾放置一个虚拟语句会更接近于 continue 的作用:跳过循环体中所有剩余语句,然后继续下一次迭代。 - Martijn Pieters
啊,好的,我错过了 OP 想要跳过的部分。是否可以运行其余代码并在下一次(或任何进一步)迭代时停止?我一直在尝试使用 unt[il] 但无法通过迭代推进。 - 0xc0de
@0xc0de until 用于跳出循环。我只需在循环语句或循环体的第一条语句上添加断点,然后使用 c 命令即可。 - Martijn Pieters
是的,这就是我一直在做的,但我想知道是否有更好的方法,当我想跳过一些迭代并为特定条件(例如迭代中的特定值)进行调试时,而不添加条件断点(if value == 'debug-worthy':pdb.set_trace())。谢谢。 - 0xc0de
@0xc0de b(reak)命令也可以加上一个条件。 - Martijn Pieters

8
听起来有些奇怪,但你应该能够使用jump command。你可能需要在循环结束时添加一个pass语句,以便跳到循环的末尾。如果您不确定代码的行号,可以使用ll查找循环的行号。
> c:\run.py(5)<module>()
-> print(i)
(Pdb) ll
  1     import pdb
  2     
  3     for i in range(10):
  4         pdb.set_trace()
  5  ->     print(i)
  6         pass
(Pdb) j 6
> c:\run.py(6)<module>()
-> pass
(Pdb) c
> c:\python\run.py(4)<module>()
-> pdb.set_trace()
(Pdb) c
1
> c:\python\run.py(5)<module>()
-> print(i)

值得注意的是,跳转到for行将重新启动循环。

那是一个解决方案。非常感谢!不过,如果有人知道在上下文中执行 continue 语句的解决方案,那就更好了。 - Andor

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