2

据我所知,python 调试器 pdb 一次可以告诉步骤。

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

在像 pdb 这样的调试器中有什么方法可以在一行代码中“微步”?例如,有没有办法在表达式的每个部分完成之后单步执行,然后再将值传递给表达式的下一部分并能够检查每个点返回的内容?

我意识到如果可以编辑文件(这并不总是可能或实际的),那么可以通过插入换行符或添加中间值来打破这样的行,但并不总是可以编辑文件,特别是如果你是走进图书馆。

4

2 回答 2

0

首先,根据我的经验,人们不会在 Python 中编写长的单行表达式……当然可以,但是 PEP 8 不鼓励这样做,而且您通常学习的教程、stdlib 和其他示例代码看起来不像那样.

然而,人们确实会写出非常复杂的表达式。特别是,他们使用诸如推导和迭代器之类的东西。

无论如何,无论哪种方式,这种事物的子表达式是什么都有些模棱两可,因此不清楚进入它们应该意味着什么。

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

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

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

在幕后,这实际上是这样的:

x = _hidden_func(range(3))

并且那个隐藏函数(实际上被命名为<listcomp-123912576>, not _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已经可以做到这一点……但它无法向您展示任何有趣的东西。

显然,您可以使用此代码做很多事情。您可以选择其中一项并编写执行此操作的自定义代码。这个可视化工具显示了一种可能性。

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

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

于 2013-09-17T23:28:08.803 回答
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...

更多信息!和其他命令在这里

于 2013-09-18T00:02:09.197 回答