为什么导入pdb;在Spyder中以不同方式调用时,pdb.set_trace会触发两种不同的调试方案吗?

时间:2018-01-15 10:54:55

标签: python debugging ipython spyder

这是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行:

enter image description here

继续Continue Execution until next breakpoint (F12)会直接转到第8行。另请注意,在下面的屏幕截图中,变量资源管理器中填充了变量inamesvalues。在使用Run Current Line (F10)

执行其余代码时,会添加和更新其他变量

enter image description here

或者你可以Continue Execution until next breakpoint (F12)并以这种方式完成程序。将前者一直做到foo()清除变量资源管理器,在ipdb调试器中打印--Return--,然后退出调试器。

我想我应该每次都采用这种方式做事,但我对Spyder提供的运行代码的其他选项非常感兴趣。我特别喜欢使用#%%和Ctrl + Enter定义和运行单元格。

场景2 - 在包含整个代码的单元格中按Ctrl + Enter

Ctrl + Enter在单元格高亮显示第8行,并填充变量资源管理器:

enter image description here

继续Continue Execution until next breakpoint (F12)清除变量资源管理器并像以前一样退出调试器:

enter image description here

这也很好,但这是我的理由:

场景3 - 运行和调试多个单元格

当我调试大型数据科学项目的代码片段时,我经常最终在一个地方定义一些变量,并希望调试在其他地方使用这些变量作为输入的函数。这就是为什么我经常会遇到下面的情况,我在一个单元格中定义了变量,并在另一个单元格中使用相同的变量进行For循环:

包含变量的单元格

Cell1

包含For Loop的单元格

Cell2

但按Ctrl + Enter并继续运行当前行(F10)会触发interactiveshell.py内的混乱情况:

enter image description here

现在,问题是:

  1. 这里发生了什么?
  2. 可以避免吗?
  3. 为什么不能像这样调试单元格(或突出显示的代码+ f9)?
  4. 感谢您的任何建议!

1 个答案:

答案 0 :(得分: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方法的工作。