调试python单步执行(微步?)

时间:2013-09-17 22:52:36

标签: python debugging

python调试器,pdb,据我所知,一次只能说一行。

Python是人们倾​​向于在其中编写长单行表达式的语言之一。

在调试器中是否有某种方式像pdb一样“microstep” 一行代码?在表达式的每个部分完成之前,有没有办法在将值移交到表达式的下一部分并且能够检查每个点返回的内容之后单步执行?

我意识到如果文件可以被编辑(这并不总是可行或不实用),那么可以通过插入换行符或添加中间值来分解这样的行,但是并不总是可以编辑文件,特别是如果你正踩到图书馆。

2 个答案:

答案 0 :(得分:0)

首先,根据我的经验,人们不会在Python中编写长的单行表达式...当然可以,但PEP 8不鼓励它,以及教程,stdlib和其他示例代码你通常从中学习并不像那样。

然而,人们写非常复杂的表达式。特别是,他们使用诸如理解和迭代器之类的东西。

无论如何,无论哪种方式,这种事物的子表达式都有点含糊不清,所以不清楚它应该是什么意思进入它们。

让我们举一个简单的例子:

x = [i*2 for i in range(3)]

显然,range(3)是一个子表达式。但还有什么? i*2是子表达式吗?或者其中三个?

在幕后,实际上看起来是:

x = _hidden_func(range(3))

这个隐藏的函数(实际上命名为<listcomp-123912576>,而不是_hidden_func)是在编译时直接从字节码构建的,并不映射到任何实际有效的Python代码。它大致是这样的:

def _hidden_func(iterable):
    result = []
    iterator = iter(iterable)
    while True:
        try:
            i = next(iterator)
            result.append(i*2)
        except StopIteration:
            return result

...但它使用快速列表构建和next - with - StopIteration - 处理不映射到您实际可写的任何内容的字节码。

因此,为了完全看到i*2,您需要进入一个没有源代码的函数,甚至无法动态地反编译成源代码。

事实上,pdb已经可以做到这一点......但它无法向您展示任何有趣的内容。

显然,您可以对此代码执行各种操作。你可以选择其中一个并编写自定义代码。 This visualizer显示了一种可能性。

同一个可视化工具将长而简单的表达式(如x = 2 * i**2 + 3 * i + 4)视为一个步骤,但您可以通过例如单步执行字节码并反编译每个“有趣的”字节码来明确处理。

但同样,你必须决定什么算“有趣”,并编写适当的代码。 i**2可能感兴趣,但i呢?您是否关心它是否正在进行本地,闭包或全局查找以获取它,或查找的内容,或者您​​只是想跳过它?

答案 1 :(得分:0)

就像你说的那样,没有“微步”。仅step

但我经常使用!语句来执行部分行。要使用上面的示例:

>>> def foo(i):
...     return 2*i**2 + 3*i + 4
>>>
>>> import pdb
>>> pdb.runcall(foo, 5)
-> return 2*i**2 + 3*i + 4
(Pdb) !2*i**2
50
(Pdb) !3*i + 4
19

如果行中有多个函数但我只想进入其中一个函数,我使用debug进入递归调试器:

>>> def foo(i):
...     return fn(i) + fn2(i) * fn3(i)
>>>
>>> import pdb
>>> pdb.runcall(foo, 5)
-> return fn(i) + fn2(i) * fn3(i)
(Pdb) debug fn3(i)
ENTERING RECURSIVE DEBUGGER
> <string>(1)<module>()
((Pdb))
# step through fn3 code...

有关!和其他命令here的更多信息。