Python 为什么要进口pdb;pdb.set_trace在Spyder中调用不同时会触发两种不同的调试场景?

Python 为什么要进口pdb;pdb.set_trace在Spyder中调用不同时会触发两种不同的调试场景?,python,debugging,ipython,spyder,Python,Debugging,Ipython,Spyder,这是我们的后续问题 为什么导入pdb;pdb.set_trace在Spyder中以不同方式调用时触发两种不同的调试场景? 下面是针对上面提到的问题编辑的示例代码 代码: def foo(): names = ['A', 'B', 'C'] values = [11,12,13] i = 0 import pdb; pdb.set_trace() for n in names: variable = str(n) + ' = ' + st

这是我们的后续问题

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

下面是针对上面提到的问题编辑的示例代码

代码:

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()
Scenario1-
运行文件(F5)
继续执行,直到下一个断点(F12)
运行当前行(F10)

这个程序运行得很好。让我解释一下,为了上下文:

运行文件(F5)
突出显示第2行:

继续执行
继续执行,直到下一个断点(F12)
将您直接带到第8行。还请注意,在下面的屏幕截图中,变量浏览器中填充了变量
i
名称
值。当您使用
运行当前行(F10)
浏览代码的其余部分时,会添加和更新其他变量:

或者您可以
继续执行,直到下一个断点(F12)
,然后以这种方式完成过程。执行前一步直到
foo()
清除变量资源管理器,在ipdb调试器中打印--Return--,然后退出调试器

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

场景2-按住Ctrl键并输入包含整个代码的单元格

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

继续执行
继续执行,直到下一个断点(F12)
清除变量资源管理器并像前面一样退出调试器:

这也很好,但我的情况是:

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

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

包含变量的单元格

包含For循环的单元格

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

现在,问题是:

  • 这是怎么回事
  • 这能避免吗
  • 为什么不能像这样调试单元格(或突出显示的代码+f9)
  • 谢谢你的建议

    (这里是Spyder maintainer)我认为问题在于您试图评估函数范围内的单元格。在本例中,所有变量都是作用域的局部变量,因此您无法对
    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()
    
    这使我能够毫无问题地调试
    操纵
    方法的工作