如何在 Python 中使用 Spyder 进行高效调试?
How do I debug efficiently with Spyder in Python?
我喜欢 Python 并且我喜欢 Spyder,但我发现使用 Spyder 进行调试非常糟糕!
- 每次下断点都需要按两个按钮:首先
调试然后继续按钮(它在第一行暂停
自动)这很烦人。
- 此外,我有一个糟糕的 ipdb>> 控制台,而不是具有自动完成等功能的标准 iPython 控制台。
- 最糟糕的是,即使我写打印或简单的评估来试图找出错误是什么,这个控制台也经常死机。这比MATLAB差多了。
- 最后但同样重要的是,如果我从
ipdb>> console,在里面下个断点,它不会停在那里。
看来我必须在开始之前把断点放在那里
调试 (Ctrl+F5).
你有解决方案吗,或者你能告诉我你是如何调试 Python 脚本和函数的吗?
我在 Windows 8.1 64 位上使用全新安装的 Anaconda。
(Spyder maintainer here)我们2020年11月发布的4.2.0版本后,在Spyder中的调试体验相当不错.我们现在提供的是来自 Matlab 的人们对调试器的期望,即类似于 IPython 的东西,让您在当前断点或帧处检查和绘制变量。
现在谈谈你的观点:
如果您尝试调试的文件中存在断点,则 Spyder 会进入调试模式并继续直到遇到第一个断点。如果它存在于另一个文件中,那么您仍然需要先按 Debug
,然后按 Continue
。
IPdb
是 IPython 调试器控制台。在 Spyder 4.2.0 或更高版本中,它带有代码完成、语法突出显示、使用 up/down 箭头浏览命令的历史记录(与 IPython 历史记录分开)、多行代码评估以及内联和使用 Matplotlib 进行交互式绘图。
此问题现已修复。此外,为了避免 Python 代码和 Pdb 命令之间的冲突,如果您有(例如)一个名为 n
的变量并在提示中写入 n
以查看其值,我们将显示它而不是 运行ning n
Pdb 命令。要改为 运行 该命令,您必须在其前面加上感叹号,如下所示:!n
这也已修复。您可以在 IPdb
中设置断点,它们将在您当前的会话中被考虑。
关于第 3 点的一个小补充:
在我看来,调试控制台经常冻结、打印、评估等,但按下停止(退出调试)按钮通常会将其返回到调用堆栈的底部,然后我可以返回('u') 到我正在调试的框架。值得一试。这可能适用于更高版本的 Spyder (2.3.5.2)
以下是我在 Spyder 中调试以避免冻结 IDE 的方法。如果我在调试模式下更改脚本,我会这样做。
- 我关闭了当前的IPython(调试)控制台[x]
- 打开一个新的[菜单栏->控制台->打开一个IPython控制台]
- 再次进入调试模式[蓝色播放暂停按钮]。
仍然有点烦人,但它有清除(重置)变量列表的额外好处。
pdb 调试器与 常规 python 一起工作得很好。所以在 Spyder 中,只要我想进行交互式调试,我就切换到 python 控制台。
import pdb
def yourfunction():
# Interesting stuff done here
pdb.set_trace()
关于使用 pdb 进行调试的精彩介绍 https://pythonconquerstheuniverse.wordpress.com/category/python-debugger/
调试工作流程
你要明白其实你是在使用不同的集成Python debugger pdb
and ipdb
(which uses pdb
and which can be accessed using the module 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
我做的第一件事是使用魔术命令 %debug
从 iPython 调用 pdb,您可以使用 %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
。您可以在 official docs 中找到所有命令,也可以使用命令 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
(感叹号和第一个值之间没有space)。
很明显 b 和 d 是字符串,以防我们可以使用:
ipdb> whatis b
<type 'str'>
使用断点更深入
70% 的时间 %debug
会为您指出解决方案。当您需要更多功能时,例如 breakpoints 是使用 Spyder 的时候了。在这种情况下,我们想了解为什么 b
是一个字符串,我们在它旁边放置了一个断点(在编辑器中的行号旁边双击 window)。我发现 更好 使用标准 Python 控制台而不是 IPython 控制台进行调试,因此 select 在开始调试之前使用控制台:
然后打开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 console 中使用标准 pdb 的一个重要功能是你有自动竞争,你可以使用变量 explorer 而不是使用 whatis
和 pp
:
使用变量资源管理器,您还可以更改变量的值,从而使事情变得更快。
条件断点
另外一种更巧妙的定位错误的方法是使用条件断点(Shift+F12) Spyder 的一大优势是调试和使用列表断点。当条件为 True
时激活条件断点 在我们的例子中,我们想要定位 b 成为字符串的位置,因此条件为:type(b) == str
。我通常会放置很多条件断点,看哪些满足条件。为此,请不要使用 Shift+F12 而是在该行旁边双击放置正常断点并转到 Debug->List breakpoints 和将 table 中的条件复制并粘贴到每个断点,如下图所示。
从这里开始使用的命令是:
(Pdb) c # go to the first
(Pdb) u # it helps to understand when it happened
(Pdb) d # come back to the breakpoint
您可以使用调试快捷键,例如:
跨过 F10
进入F11
在工具>首选项>键盘快捷键
之前显然没有人提到过这两个:
在 Python 之前,我使用的是 VBA。虽然它是一种相对较旧的语言,不定期更新,但我喜欢 VBA 的一件事是调试功能。我遇到的最接近 VBA 或者也可以称为 "visual debugging" 的 2 个调试函数是:
1-PyCharm Debugger
This 6 分钟视频演示 PyCharm 调试器。
2-PixieDebugger - The Visual Python Debugger for Jupyter Notebooks You’ve Always Wanted
由于许多编码人员倾向于使用 JupyterNotebook,因此此调试器会派上用场。
PixieDebugger 与 PyCharm 调试器几乎相同。在这里就不细说了。
不过你可以参考这个link
我喜欢 Python 并且我喜欢 Spyder,但我发现使用 Spyder 进行调试非常糟糕!
- 每次下断点都需要按两个按钮:首先 调试然后继续按钮(它在第一行暂停 自动)这很烦人。
- 此外,我有一个糟糕的 ipdb>> 控制台,而不是具有自动完成等功能的标准 iPython 控制台。
- 最糟糕的是,即使我写打印或简单的评估来试图找出错误是什么,这个控制台也经常死机。这比MATLAB差多了。
- 最后但同样重要的是,如果我从 ipdb>> console,在里面下个断点,它不会停在那里。 看来我必须在开始之前把断点放在那里 调试 (Ctrl+F5).
你有解决方案吗,或者你能告诉我你是如何调试 Python 脚本和函数的吗?
我在 Windows 8.1 64 位上使用全新安装的 Anaconda。
(Spyder maintainer here)我们2020年11月发布的4.2.0版本后,在Spyder中的调试体验相当不错.我们现在提供的是来自 Matlab 的人们对调试器的期望,即类似于 IPython 的东西,让您在当前断点或帧处检查和绘制变量。
现在谈谈你的观点:
如果您尝试调试的文件中存在断点,则 Spyder 会进入调试模式并继续直到遇到第一个断点。如果它存在于另一个文件中,那么您仍然需要先按
Debug
,然后按Continue
。IPdb
是 IPython 调试器控制台。在 Spyder 4.2.0 或更高版本中,它带有代码完成、语法突出显示、使用 up/down 箭头浏览命令的历史记录(与 IPython 历史记录分开)、多行代码评估以及内联和使用 Matplotlib 进行交互式绘图。此问题现已修复。此外,为了避免 Python 代码和 Pdb 命令之间的冲突,如果您有(例如)一个名为
n
的变量并在提示中写入n
以查看其值,我们将显示它而不是 运行ningn
Pdb 命令。要改为 运行 该命令,您必须在其前面加上感叹号,如下所示:!n
这也已修复。您可以在
IPdb
中设置断点,它们将在您当前的会话中被考虑。
关于第 3 点的一个小补充:
在我看来,调试控制台经常冻结、打印、评估等,但按下停止(退出调试)按钮通常会将其返回到调用堆栈的底部,然后我可以返回('u') 到我正在调试的框架。值得一试。这可能适用于更高版本的 Spyder (2.3.5.2)
以下是我在 Spyder 中调试以避免冻结 IDE 的方法。如果我在调试模式下更改脚本,我会这样做。
- 我关闭了当前的IPython(调试)控制台[x]
- 打开一个新的[菜单栏->控制台->打开一个IPython控制台]
- 再次进入调试模式[蓝色播放暂停按钮]。
仍然有点烦人,但它有清除(重置)变量列表的额外好处。
pdb 调试器与 常规 python 一起工作得很好。所以在 Spyder 中,只要我想进行交互式调试,我就切换到 python 控制台。
import pdb
def yourfunction():
# Interesting stuff done here
pdb.set_trace()
关于使用 pdb 进行调试的精彩介绍 https://pythonconquerstheuniverse.wordpress.com/category/python-debugger/
调试工作流程
你要明白其实你是在使用不同的集成Python debugger pdb
and ipdb
(which uses pdb
and which can be accessed using the module 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
我做的第一件事是使用魔术命令 %debug
从 iPython 调用 pdb,您可以使用 %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
。您可以在 official docs 中找到所有命令,也可以使用命令 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
(感叹号和第一个值之间没有space)。
很明显 b 和 d 是字符串,以防我们可以使用:
ipdb> whatis b
<type 'str'>
使用断点更深入
70% 的时间 %debug
会为您指出解决方案。当您需要更多功能时,例如 breakpoints 是使用 Spyder 的时候了。在这种情况下,我们想了解为什么 b
是一个字符串,我们在它旁边放置了一个断点(在编辑器中的行号旁边双击 window)。我发现 更好 使用标准 Python 控制台而不是 IPython 控制台进行调试,因此 select 在开始调试之前使用控制台:
然后打开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 console 中使用标准 pdb 的一个重要功能是你有自动竞争,你可以使用变量 explorer 而不是使用 whatis
和 pp
:
使用变量资源管理器,您还可以更改变量的值,从而使事情变得更快。
条件断点
另外一种更巧妙的定位错误的方法是使用条件断点(Shift+F12) Spyder 的一大优势是调试和使用列表断点。当条件为 True
时激活条件断点 在我们的例子中,我们想要定位 b 成为字符串的位置,因此条件为:type(b) == str
。我通常会放置很多条件断点,看哪些满足条件。为此,请不要使用 Shift+F12 而是在该行旁边双击放置正常断点并转到 Debug->List breakpoints 和将 table 中的条件复制并粘贴到每个断点,如下图所示。
从这里开始使用的命令是:
(Pdb) c # go to the first
(Pdb) u # it helps to understand when it happened
(Pdb) d # come back to the breakpoint
您可以使用调试快捷键,例如: 跨过 F10 进入F11 在工具>首选项>键盘快捷键
之前显然没有人提到过这两个:
在 Python 之前,我使用的是 VBA。虽然它是一种相对较旧的语言,不定期更新,但我喜欢 VBA 的一件事是调试功能。我遇到的最接近 VBA 或者也可以称为 "visual debugging" 的 2 个调试函数是:
1-PyCharm Debugger
This 6 分钟视频演示 PyCharm 调试器。
2-PixieDebugger - The Visual Python Debugger for Jupyter Notebooks You’ve Always Wanted
由于许多编码人员倾向于使用 JupyterNotebook,因此此调试器会派上用场。 PixieDebugger 与 PyCharm 调试器几乎相同。在这里就不细说了。
不过你可以参考这个link