如何使用Python中的spyder有效地进行调试?


75

我喜欢Python,也喜欢Spyder,但是我发现用Spyder调试很糟糕!

  • 每次我设置一个断点时,我都需要按两个按钮:首先是调试,然后是继续按钮(它会自动在第一行暂停),这很烦人。
  • 而且,与其让标准的iPython控制台具有自动完成功能,不如说我有一个糟糕的ipdb >>控制台,这只是垃圾。
  • 最糟糕的是,即使我进行打印或进行简单评估以找出错误所在,该控制台也会非常频繁地冻结。这比matlab差得多。
  • 最后但并非最不重要的一点是,如果我从ipdb >>控制台中调用一个函数,并在其中放置一个断点,它将不会就此停止。似乎我必须在开始调试(ctrl + F5)之前在其中放置断点。

您是否有解决方案,或者可以告诉我如何调试python脚本和函数?

我在Windows 8.1 64位上使用全新安装的Anaconda。


与复杂的调试无关,但是我经常需要在脚本中间停下来,使用特定的变量集在控制台中进行进一步的开发。我通常只是sys.exit()临时输入,但是如果有断点选项,会更方便。
威克

Answers:


54

此处为Spyder开发人员)我们知道Spyder的调试经验远非理想。我们现在提供的功能与标准的Python调试器非常相似,但是我们正在努力改进下一个主要版本中的功能,以提供更接近任何科学家对调试器的期望的东西(总之,常规的IPython控制台可以您可以在当前断点处检查并绘制变量)。

现在谈谈您的观点:

  1. 这是真的。我们正在考虑进行改进,以便如果用户按下“运行”按钮,并且当前文件中存在断点,则Spyder进入调试模式并执行程序,直到遇到第一个断点为止。

  2. ipdb是IPython调试器控制台。不幸的是,由于IPython体系结构的限制,它非常有限(没有代码完成,也没有带有箭头的历史记录)。此外,不可能在任何一个ipdb或常规pdb控制台中运行任意Python代码。您可以在ipdb其中运行的命令是评估其中的help命令时可以阅读的命令。

  3. 正如我所说,这是因为您无法评估任意Python代码。

  4. 您需要在我们的编辑器中放置新的断点,以便它们与我们的Python / IPython控制台同步


13
我想指出另一个我认为很重要的功能。当前,只能通过“调试文件”进行调试,该调试文件在单独的会话中从头到尾运行一个文件,而忘记了我可能在控制台中定义的所有变量。能够在启动特定功能的同时传递其在我的工作空间中已定义的变量(这有时重新计算有时会很昂贵),这将是很棒的选择
Leo

1
@neuronet,它已经在起作用,但是仅当您按下“调试”按钮(即蓝色的“播放/暂停”按钮)时。
卡洛斯·科尔多瓦

2
@neuronet,请提出一个问题,以更好地了解您的情况。
卡洛斯·科尔多瓦

2
@CarlosCordoba好的,可以,我会花点时间尝试不做任何愚蠢的事情。:)
eric

1
@CarlosCordoba我想我有点起作用了。我必须确保整个文件没有任何错误,然后单击“播放/暂停”按钮(因为像ctrl-F12这样的事情什么也没做,直到我使用ctrl-F5进入调试模式为止)。现在,我可以对此进行更多探讨,但也可以更好地了解此处的OP和您的回答。Matlab很好用,这让我习惯了……有些清晰的文档在这里也要走很长的路,特别是对于恢复那些希望Spyder像Matlab的Matlab用户。
eric

27

调试工作流程

您必须了解,实际上您正在使用Python调试器pdb 和的 不同集成ipdb(和使用pdb,并且可以使用模块访问ipdb)。我希望这个简单的例子可以帮助您更好地使用它。

假设您要调试以下代码:

def Waiting_fun():                      #1 line number one
    for i in range(100):                #2
        pass                            #3
                                        #4 
def New_sum(lista, to_s = False):       #5
    result = 0                          #6
    print 1                             #7
    for i in lista:                     #8
        print "summed"                  #9   
        result +=i                      #10
    Waiting_fun()                       #11
    if to_s:                            #12
        result = str(result)
    return result
a = New_sum([1,4,5,7,8])
b = New_sum([1,4],1)
c = 456
d = New_sum([6,8,9],1)
final_result = a*b*c*d
Out: Type error

使用iPython%debug快速进行首次调试

%debug

我要做的第一件事是使用magic命令从iPython调用pdb %debug,您可以使用将它设置为默认机制%pdb

%debug
> /home/opdate/Desktop/test.py(23)<module>()
     19 a = New_sum([1,4,5,7,8])
     20 b = New_sum([1,4],1)
     21 c = 456
     22 d = New_sum([6,8,9],1)
---> 23 final_result = a*b*c*d

午餐后pdb。您可以在官方文档中找到所有命令,也可以使用该命令h显示它们。在此阶段,我唯一使用的命令是:

  • p :打印您指定的变量
  • pp :漂亮的版画
  • args:如果您在函数内部,它将打印参数
  • pp locals() :可以打印所有变量,但大多数情况下是一团糟!
  • ! 如果您想避免与中列出的命令冲突,请使用它 h
  • whatis variable_name:等价于类型(variable_name)
  • u :将当前帧在堆栈跟踪中上移一层(移至较旧的帧)。
  • d :将当前帧在堆栈跟踪中向下移动一级(到新的帧)。
  • q :完成后,您可以使用q退出

在我们的情况下:

ipdb> pp a,b,c,d
(25, '5', 456, '23')

ipdb> !a,b,c,d(星号与第一个值之间没有空格)。很明显,b和d是字符串,以防我们可以使用:

ipdb> whatis b
<type 'str'>

使用断点更深入

70%的时间%debug指向您解决方案。当您需要断点之类的更多功能时,就可以使用Spyder。在这种情况下,我们想了解为什么b在字符串旁边放置一个断点(在编辑器窗口中双击行号旁边)。我发现使用标准Python控制台而不是IPython控制台进行调试要好得多,因此在开始调试之前请选择控制台: 在此处输入图片说明

然后打开 variable explorer是否有任何变量将其删除。我使用Ctrl+F5开始调试,您可以使用顶部的按钮,但我更喜欢使用如下所示的快捷方式:

在此处输入图片说明

(Pdb) c # we go to the breakpoint 
(Pdb) s # we step into the function
(Pdb) args # we see what parameters are inserted
(Pdb) s # going step-by-step
(Pdb) ⏎ # series of Enters go line by line quicker
#Here I'll use  whatis command but in fact I just look to
# the type in variable explorer of spyder.
(Pdb) whatis result #check if result is still int
(Pdb) unt #or until -useful to exiting from loops see doc.
(Pdb) n # we  don't  enter to the Waiting_fun function
(Pdb) s # going step-by-step
(Pdb) whatis result #we find that there the int is converted
(Pdb) j 6 # for double checking we jump back to 6 were the result is assigned 
# We may be tempted to j(ump) to line 12 but doing so we would skip all the code
#for avoiding a series of `s`,`unt` and `n` we can use this solution:
(Pdb) tbreak 12 #set a new temporary breakpoint. Also `b` it's ok most of the time
(Pdb) c  # go to it 
(Pdb) j 6 # we jump to 6 the code we jump is NOT executed
(Pdb) whatis result# we find that if we jump 12-13 result is still int

现在我们已经找到了错误。我们还可以测试一个解决方案,将步骤重复到12,然后设置to_s = False

(Pdb) to_s = False #!to_s = False to be on the safe side

有用。在Python控制台中使用标准pdb的一项重要功能是具有自动竞争功能,可以使用变量资源管理器而不是使用whatisand pp

在此处输入图片说明

使用变量浏览器,您还可以更改变量的值,从而使事情变得更快。

条件断点

定位错误的另一种更聪明的方法是使用条件断点Shift+ F12),Spyder的一大优势是可以调试和使用列表断点。当条件为时,条件断点被激活True在我们的例子中,我们想定位b成为字符串的位置,因此条件为:type(b) == str。我通常会放置很多条件断点,并查看哪些条件断点。为此,请不要使用Shift+,F12而是将正常断点双击该行旁边,然后转到Debug-> List断点,然后将表中的条件复制并粘贴到每个断点,如下图所示。

在此处输入图片说明

从这里使用的命令是:

(Pdb) c  # go to the first
(Pdb) u # it helps to understand when it happened
(Pdb) d # come back to the breakpoint

4

pdb调试器可以与常规python一起正常工作。因此,在Spyder中,每当我要进行交互式调试时,我都只是切换到python控制台。

import pdb

def yourfunction():
    # Interesting stuff done here
    pdb.set_trace() 

不错的pdb调试简介https://pythonconquerstheuniverse.wordpress.com/category/python-debugger/


1
不幸的是:NOTE: The Python console is going to be REMOVED in Spyder 3.2. Please start to migrate your work to the IPython console instead.
C8H10N4O2 '18年

1

这是我在Spyder中进行调试的方法,以避免冻结IDE。如果我在调试模式下更改了脚本,则会执行此操作。

  1. 我关闭了当前的IPython(调试)控制台[x]
  2. 打开一个新的[菜单栏->控制台->打开IPython控制台]
  3. 再次进入调试模式[蓝色播放暂停按钮]。

仍然有点烦人,但是它还有清除(重置)变量列表的额外好处。


1

显然没有人提到过这两个:

在使用Python之前,我使用的是VBA。尽管它是一种相对较旧的语言,不会定期更新,但是我对VBA的一件事是调试功能。我遇到的最接近VBA或也可以称为“可视调试”的2个调试功能是:

1-PyCharm调试器

6分钟的视频演示了PyCharm调试器。

2-PixieDebugger-您一直想要的适用于Jupyter笔记本的Visual Python调试器

由于许多编码人员倾向于使用JupyterNotebook,因此该调试器会派上用场。PixieDebugger与PyCharm调试器几乎相同。我将不在这里详细介绍。

但是你可以参考这个链接


2
问题是关于Spyder的,您提到的调试器都不能在Spyder中使用。
卡洛斯·科尔多瓦

1
我对此很清楚。我只是强调了不同类型的可视化python调试器。不一定是间谍。
mcagriardic

0

关于第3点的一个小额外要求:

在我看来,调试控制台经常冻结,进行打印,评估等,但是按停止(退出调试)按钮通常会使它回到调用堆栈的底部,然后我可以返回('u')到我正在调试的框架。值得一试。这可能适用于更高版本的Spyder(2.3.5.2)


0

您可以使用以下调试快捷方式键:在工具>首选项>键盘快捷方式中单步执行F10进入F11

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.