- 内容提要
- 作者简介
- 技术评审者简介
- 致谢
- 译者序 会编程的人不一样
- 前言
- 本书的读者对象
- 编码规范
- 什么是编程
- 本书简介
- 下载和安装 Python
- 启动 IDLE
- 如何寻求帮助
- 聪明地提出编程问题
- 小结
- 第一部分 Python 编程基础
- 第1章 Python 基础
- 第2章 控制流
- 第3章 函数
- 第4章 列表
- 第5章 字典和结构化数据
- 第6章 字符串操作
- 第二部分 自动化任务
- 第7章 模式匹配与正则表达式
- 第8章 读写文件
- 第9章 组织文件
- 第10章 调试
- 第11章 从 Web 抓取信息
- 第12章 处理 Excel 电子表格
- 第13章 处理 PDF 和 Word 文档
- 第14章 处理 CSV 文件和 JSON 数据
- 第15章 保持时间、计划任务和启动程序
- 第16章 发送电子邮件和短信
- 第17章 操作图像
- 第18章 用 GUI 自动化控制键盘和鼠标
- 附录A 安装第三方模块
- 附录B 运行程序
- 附录C 习题答案
10.5 IDLE的调试器
“调试器”是IDLE的一项功能,让你每次执行一行程序。调试器将运行一行代码,然后等待你告诉它继续。像这样让程序运行“在调试器之下”,你可以随便花多少时间,检查程序运行时任意一个时刻的变量的值。对于追踪缺陷,这是一个很有价值的工具。
要启用IDLE的调试器,就在交互式环境窗口中点击DebugDebugger。这将打开调试控制(Debug Control)窗口,如图10-1所示。
图10-1 调试控制窗口
当调试控制窗口出现后,勾选全部4个复选框:Stack、Locals、Source和Globals。这样窗口将显示全部的调试信息。调试控制窗口显示时,只要你从文件编辑器运行程序,调试器就会在第一条指令之前暂停执行,并显示下面的信息:
· 将要执行的代码行;
· 所有局部变量及其值的列表;
· 所有全局变量及其值的列表。
你会注意到,在全局变量列表中,有一些变量你没有定义,诸如 builtins 、 doc 、 file ,等等。它们是Python在运行程序时,自动设置的变量。这些变量的含义超出了本书的范围,你可以暂时忽略它们。
程序将保持暂停,直到你按下调试控制窗口的5个按钮中的一个:Go、Step、Over、Out或Quit。
10.5.1 Go
点击Go按钮将导致程序正常执行至终止,或到达一个“断点”(断点在本章稍后介绍)。如果你完成了调试,希望程序正常继续,就点击Go按钮。
10.5.2 Step
点击Step按钮将导致调试器执行下一行代码,然后再次暂停。如果变量的值发生了变化,调试控制窗口的全局变量和局部变量列表就会更新。如果下一行代码是一个函数调用,调试器就会“步入”那个函数,跳到该函数的第一行代码。
10.5.3 Over
点击Over按扭将执行下一行代码,与Step按钮类似。但是,如果下一行代码是函数调用,Over按钮将“跨过”该函数的代码。该函数的代码将以全速执行,调试器将在该函数返回后暂停。例如,如果下一行代码是print() 调用,你实际上不关心内建print() 函数中的代码,只希望传递给它的字符串打印在屏幕上。出于这个原因,使用Over按钮比使用Step按钮更常见。
10.5.4 Out
点击Out按钮将导致调试器全速执行代码行,直到它从当前函数返回。如果你用Step按钮进入了一个函数,现在只想继续执行指令,直到该函数返回,那就点击Out按钮,从当前的函数调用“走出来”。
10.5.5 Quit
如果你希望完全停止调试,不必继续执行剩下的程序,就点击Quit按钮。Quite按钮将马上终止该程序。如果你希望再次正常运行你的程序,就再次选择DebugDebugger,禁用调试器。
10.5.6 调试一个数字相加的程序
打开一个新的文件编辑器窗口,输入以下代码:
print('Enter the first number to add:') first = input() print('Enter the second number to add:') second = input() print('Enter the third number to add:') third = input() print('The sum is ' + first + second + third)
将它保存为buggyAddingProgram.py,不启用调试器,第一次运行它。程序的输出像这样:
Enter the first number to add: 5 Enter the second number to add: 3 Enter the third number to add: 42 The sum is 5342
这个程序没有崩溃,但求和显然是错的。让我们启用调试控制窗口,再次运行它,这次在调试器控制之下。
当你按下F5或选择RunRun Module(启用DebugDebugger,选中调试控制窗口的所有4个复选框),程序启动时将暂停在第1行。调试器总是会暂停在它将要执行的代码行上。调试控制窗口看起来如图10-2所示。
图10-2 程序第一次在调试器下运行时的调试控制窗口
点击一次Over按钮,执行第一个print() 调用。这里应该使用Over按钮,而不是Step,因为你不希望进入到print() 函数的代码中。调试控制窗口将更新到第2行,文件编辑器窗口的第2行将高亮显示,如图10-3所示。这告诉你程序当前执行到 哪里。
图10-3 点击Over按钮后的调试控制窗口
再次点击Over按钮,执行input() 函数调用,当IDLE等待你在交互式环境窗口中为input() 调用输入内容时,调试控制窗口中的按钮将被禁用。输入5并按回车。调试控制窗口按钮将重新启用。
继续点击Over按钮,输入3和42作为接下来的两个数,直到调试器位于第7行,程序中最后的print() 调用。调试控制窗口应该如图10-4所示。可以看到,在全局变量的部分,第一个、第二个和第三个变量设置为字符串值,而不是整型值。当最后一行执行时,这些字符串连接起来,而不是加起来,导致了这个缺陷。
用调试器单步执行程序很有用,但也可能很慢。你常常希望程序正常运行,直到它到达特定的代码行。你可以使用断点,让调试器做到这一点。
10.5.7 断点
“断点”可以设置在特定的代码行上,当程序执行到达该行时,它迫使调试器暂停。在一个新的文件编辑器窗口中,输入以下程序,它模拟投掷1000次硬币。将它保存为coinFlip.py。
图10-4 在最后一行的调试控制窗口。这些变量被设置为字符串,导致了这个缺陷
import random heads = 0 for i in range(1, 1001): ❶ if random.randint(0, 1) == 1: heads = heads + 1 if i == 500: ❷ print('Halfway done!') print('Heads came up ' + str(heads) + ' times.')
在半数时间里,random.randint(0,1)调用❶将返回0,在另外半数时间将返回1。这可以用来模拟50/50的硬币投掷,其中1代表正面。当不用调试器运行该程序时,它很快输出下面的内容:
Halfway done! Heads came up 490 times.
如果启用调试器运行这个程序,就必须点击几千次Over按钮,程序才能结束。如果你对程序执行到一半时heads的值感兴趣,等1000次硬币投掷完500次,可以在代码行print('Halfway done!')❷上设置断点。要设置断点,在文件编辑器中该行代码上点击右键,并选择Set Breakpoint,如图10-5所示。
图10-5 设置断点
你不会在if语句上设置断点,因为if语句会在循环的每次迭代中都执行。通过在if语句内的代码上设置断点,调试器就会只在执行进入if语句时才中断。
带有断点的代码行会在文件编辑器中以黄色高亮显示。如果在调试器下运行该程序,开始它会暂停在第一行,像平时一样。但如果点击Go,程序将全速运行,直到设置了断点的代码行。然后可以点击Go、Over、Step或Out,正常继续。
如果希望清除断点,在文件编辑器中该行代码上点击右键,并从菜单中选择Clear Breakpoint。黄色高亮消失,以后调试器将不会在该行代码上中断。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论