据我所知,python 调试器 pdb 一次可以告诉步骤。
Python 是人们倾向于编写长的单行表达式的语言之一。
在像 pdb 这样的调试器中有什么方法可以在一行代码中“微步”吗?例如,有没有办法在表达式的每个部分完成之后单步执行,然后再将值传递给表达式的下一部分并能够检查每个点返回的内容?
我意识到如果可以编辑文件(这并不总是可能或实际的),那么可以通过插入换行符或添加中间值来打破这样的行,但并不总是可以编辑文件,特别是如果你是走进图书馆。
首先,根据我的经验,人们不会在 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
?您是否关心它是否在进行本地、闭包或全局查找以获取它,或者该查找找到了什么,或者您只是想跳过它?
就像你说的,没有“微步”。只有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...
更多信息!
和其他命令在这里。