如何使用Python中的spyder高效调试?

Han*_*art 65 python debugging spyder

我喜欢Python,我喜欢Spyder,但我发现Spyder的调试非常糟糕!

  • 每次我设置一个断点,我需要按两个按钮:首先是调试然后是继续按钮(它会自动在第一行暂停),这很烦人.
  • 而且,不是让标准的iPython控制台具有自动完成功能等,而是一个糟糕的ipdb >>控制台,这只是垃圾.
  • 最糟糕的是,这个控制台非常频繁地冻结,即使我写了打印或简单的评估,试图弄清楚是什么错误.这比matlab差很多.
  • 最后但并非最不重要的,如果我从ipdb >> console中调用一个函数,并在其中放置一个断点,它将不会停在那里.在我开始调试(ctrl + F5)之前,我似乎必须将断点放在那里.

你有解决方案或者你能告诉我你如何调试python脚本和函数吗?

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

Car*_*oba 47

(Spyder dev here)我们知道Spyder的调试经验远非理想.我们现在提供的内容与标准的Python调试器非常相似,但我们正在努力改进我们下一个主要版本的内容,以提供更接近科学家对调试器的期望(简而言之,一个常规的IPython控制台)您在当前断点处检查并绘制变量).

现在关于你的观点:

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

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

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

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

  • 我想指出另一个我认为很重要的功能.目前,只能通过"调试文件"进行调试,调试文件在一个单独的会话中从头到尾运行一个文件,忘记了我在控制台中定义的所有变量.能够在传递已经在我的工作空间中定义的变量时开始调试特定函数会很棒(这有时很难重新计算) (9认同)
  • 有关状态的任何更新? (3认同)
  • @neuronet,请打开[问题](https://github.com/spyder-ide/spyder/issues)了解它,以便更好地了解您案例中发生的情况. (2认同)
  • @CarlosCordoba确定会这样做,会花时间尝试不做任何愚蠢的事情.:) (2认同)

G M*_*G M 22

调试工作流程

你必须明白,其实你正在使用不同的集成的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
Run Code Online (Sandbox Code Playgroud)

使用iPython%debug快速首次调试

%debug
Run Code Online (Sandbox Code Playgroud)

我做的第一件事是使用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
Run Code Online (Sandbox Code Playgroud)

一旦你吃完午饭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')
Run Code Online (Sandbox Code Playgroud)

或者ipdb> !a,b,c,d(在标记和第一个值之间没有空格).很明显,b和d是字符串,以防我们可以使用:

ipdb> whatis b
<type 'str'>
Run Code Online (Sandbox Code Playgroud)

使用断点更深入

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
Run Code Online (Sandbox Code Playgroud)

现在我们找到了错误.我们还可以测试一个解决方案,我们重复这个步骤直到12,我们设置to_s = False

(Pdb) to_s = False #!to_s = False to be on the safe side
Run Code Online (Sandbox Code Playgroud)

有用.在Python控制台中使用标准pdb的一个重要特性是你有自动竞争,你可以使用变量资源管理器而不是使用whatispp:

在此输入图像描述

使用变量资源管理器,您还可以更改变量的值,使事情变得更快.

条件断点

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

在此输入图像描述

从这里开始使用的命令是:

(Pdb) c  # go to the first
(Pdb) u # it helps to understand when it happened
(Pdb) d # come back to the breakpoint
Run Code Online (Sandbox Code Playgroud)