为啥要导入 pdb; pdb.set_trace 在 Spyder 中以不同方式调用时会触发两种不同的调试场景?
Posted
技术标签:
【中文标题】为啥要导入 pdb; pdb.set_trace 在 Spyder 中以不同方式调用时会触发两种不同的调试场景?【英文标题】:Why does import pdb; pdb.set_trace trigger two different debugging scenarios when called differently in Spyder?为什么要导入 pdb; pdb.set_trace 在 Spyder 中以不同方式调用时会触发两种不同的调试场景? 【发布时间】:2018-06-23 23:59:29 【问题描述】:这是Stepwise debugging of selected Python code 的后续问题。
为什么import pdb; pdb.set_trace
在 Spyder 中以不同方式调用时会触发两种不同的调试场景?
这是answer from Carlos Cordoba中针对上述问题编辑的示例代码。
代码:
def foo():
names = ['A', 'B', 'C']
values = [11,12,13]
i = 0
import pdb; pdb.set_trace()
for n in names:
variable = str(n) + ' = ' + str(values[i])
print(variable)
i += 1
foo()
场景 1 - Run file (F5)
、Continue Execution until next breakpoint (F12)
和 Run Current Line (F10)
此程序运行良好。为了上下文,让我解释一下:
Run file (F5)
突出显示第 2 行:
继续使用Continue Execution until next breakpoint (F12)
会直接转到第 8 行。另外请注意,在下面的屏幕截图中,变量资源管理器中填充了变量 i
、names
和 values
。当您使用Run Current Line (F10)
浏览其余代码时,会添加和更新其他变量:
或者您可以Continue Execution until next breakpoint (F12)
并以这种方式完成程序。将前者一直执行到foo()
会清除变量资源管理器,在 ipdb 调试器中打印 --Return-- 并退出调试器。
我想我每次都应该采用这种方式做事,但我对 Spyder 提供的其他运行代码选项非常感兴趣。而且我特别喜欢用#%% 和 Ctrl+Enter 定义和运行单元格。
场景 2 - Ctrl+Enter 在包含整个代码的单元格中
单元格中的 Ctrl+Enter 突出显示第 8 行,并填充变量资源管理器:
继续Continue Execution until next breakpoint (F12)
清除变量资源管理器并像以前一样退出调试器:
这也很好,但这是我的情况:
场景 3 - 运行和调试多个单元
当我调试大型数据科学项目的代码片段时,我经常会在一个地方定义一些变量,并希望在其他地方调试使用这些变量作为输入的函数。这就是为什么我经常遇到以下情况的原因,我在一个单元格中定义了变量,并在另一个单元格中使用相同的变量进行了 For 循环:
包含变量的单元格
包含 For 循环的单元格
但是按 Ctrl+Enter 并继续运行当前行 (F10) 会在 interactiveshell.py
中触发混乱情况:
现在,问题:
-
这是怎么回事?
可以避免这种情况吗?
为什么不能像这样调试单元格(或突出显示的代码 + f9)?
感谢您的任何建议!
【问题讨论】:
【参考方案1】:(此处是 Spyder 维护者)我认为问题在于您正在尝试评估函数范围内的单元格。在这种情况下,所有变量都是作用域的本地变量,因此您无法对 foo
进行分段计算,而这正是您尝试对我们的单元格执行的操作。
要实现你想要的,你可以使用一个类来代替。这将允许您将数据保存在类中所有方法共享的变量中,并定义您想要操作这些数据的函数/方法。一个类还允许您将数据和函数/方法巧妙地封装起来,即无需在代码的全局范围内定义。
这样,您可以简单地运行一个调用您要调试的方法的单元。在您上面发布的示例中,这将是
# %%
class Foo:
def __init__(self):
self.names = ['A', 'B', 'C']
self.values = [11,12,13]
def manipulation(self):
i = 0
import pdb; pdb.set_trace()
for n in self.names:
variable = str(n) + ' = ' + str(self.values[i])
print(variable)
i += 1
f = Foo()
# %%
f.manipulation()
这让我可以毫无问题地调试manipulation
方法的工作原理。
【讨论】:
以上是关于为啥要导入 pdb; pdb.set_trace 在 Spyder 中以不同方式调用时会触发两种不同的调试场景?的主要内容,如果未能解决你的问题,请参考以下文章
用pdb.set_trace()设断点,跟nova/api/openstack/compute/servers.py - detail() 流程