我应该使用什么选项?
有了所有这些选项,真正的初学者可能自然会问:哪一个才最适合我?通常,如果刚开始学习 Python,应该试一试 IDLE 界面。它提供了用户友好的 GUI 环境并且隐藏了一些底层的配置细节。它还带有一个与平台无关的文本编辑器用来编写脚本,且它是 Python 系统中一个标准和免费的部分。 另一方面,如果是一个有经验的程序员,可能更适应于这种简单的方式:一个窗口是选择的文本编辑器,在另一个窗口用来启动编辑的程序(通过系统命令行和图标点击,事实上,这就是我开发 Python 程序的方式,但我很久以前就有 Unix 的开发经验)。因为开发环境的选择是非常主观的,我不能提供太多通用的原则。 通常,你喜欢使用的环境就是最适合你使用的环境。我应该使用什么选项?—— 调试Python代码
自然,我的读者或学生都从不会在代码中有 Bug(:smile:),但对于你的那些可能不是那么幸运的朋友,下面是通常被真实世界的 Python 程序员使用的调试代码策略的一个快速回顾,在你开始认真编码时作为参考:- 什么都不做。 这个并不是意味着 Python 程序员不调试他们的代码 —— 但当在 Python 程序中犯错时,会得到一个非常有用和可读的错误信息(如果还没有得到,很快就会看到的)。
- 如果已经懂 Python,且特别是对自己的代码,这通常足够了 —— 阅读错误信息,然后修复标记处的行和文件。对许多人来说,这就是 Python 的调试。然而,对于还没有编写的更大系统来说,它可能并不总是理想的。
- 插入
**<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">print</font>**
语句。 很可能 Python 程序员调试代码的主要方式(也是我调试 Python 代码的方式)就是插入<u><font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">print</font></u>
语句然后再次运行。因为 Python 在更改后立即运行,这通常是获得比错误消息提供的信息更多的最快方式。<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">print</font>
语句不需要很复杂 —— 一个简单的 “我在这里” 或变量值的显示通常足够提供你所需要的上下文。只要记住在发布代码前删除或注释掉(比如在前面添加一个 #)调试 的<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">prints</font>
即可。 - 使用 IDE GUI 调试器。 对于还没有编写的更大的系统,和对于想更详细地跟踪代码的初学者来说,大多数 Python 开发 GUIs 都有某种点击的调试支持。IDLE 也有一个调试器,但它在实践中似乎用得不是很多 —— 可能是因为它没有命令行,或可能因为添加
<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">print</font>
语句通常比设置一个 GUI 调试会话要更快。 - 要学习更多,参见 IDLE 的帮助,或简单地亲自尝试一下;它的基本界面在 高级 IDLE 工具 这一节中有描述。其他的 IDE,比如 Eclipse,NetBeans,Komodo,和 Wing DIE,也都提供了高级的点击调试器;如果使用它们请参考对应的文档。
- 使用 pdb 命令行 调试器。要获得终极控制,Python 带有一个名为 pdb 的源码调试器,作为 Python 标准库的一个模块可用。在 Pdb 中,逐行键入命令,显示变量,设置和清除断点,前进到一个断点或错误,如此等等。可以通过导入 pdb,或作为一个顶层脚本来交互地启动它。因为是键入命令来控制这个会话,这两种方式都提供了一个强大的调试工具。
- Pdb 还包括了一个 postmortem 函数(pdb.pm ()),在发生一个异常后可以运行它,来获得错误发生时的信息。参见 Python 库手册和第 36 章来获取关于 pdb 的更多细节,和附录 A 来获得一个例子或使用 Python 的
<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">-m</font>
命令参数将 pdb 作为一个脚本来运行。 - 使用 Python 的 -i 命令行参数。除了添加 prints 或在 pdb 下运行,仍然可以查看错误的原因。如果从命令行运行脚本且在
<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">python</font>
和脚本名之间传递一个<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">-i</font>
参数(比如,<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">python -i m.py</font>
),当脚本存在时,Python 就将进入它的交互式解释器模式(>>> 提示符),不管它是否成功结束或碰到一个错误。 - 在这时,因为他们在顶层命名空间中,你可以打印变量的最终值来获得代码发生情况的更多细节;如果脚本失败了,它的 postmortem 模式将让你检查最近的错误。附录 A 也显示了
<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">-i</font>
的示例。 - 其他选项。对于更具体的调试需求,可以在开源领域找到额外的工具,包括对多线程程序的支持,嵌入代码,和对进程附加调试器。比如,Winpdb 系统,就是一个独立的调试器,有高级的调试支持和跨平台的 GUI 和控制台界面。
本章总结
在本章中,学习了启动程序的常见方式:通过运行交互地键入的代码,和通过使用系统命令行运行存储在文件中的代码,文件图标点击,模块导入,<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">exec</font>
调用,和如 IDLE 的 IDE GUI。这里已经介绍了许多实用的启动领域。
本章的目标是以足够的信息来武装你,让你可以开始写一些代码,这是在本书下一部分中将要做的。在那里将探索 Python 语言本身,从它的核心数据 __类型(这些对象是程序的主题)开始。
然而,首先需要完成这里学过的章节的日常测验。因为这是本书此部分的最后一章,因此它还跟有一套更完整的练习,用来测试对整个部分主题的精通程度。要获取后一组问题的帮助,或只是作为一个复习,在完成这个练习后,不要忘记参考附录 D。
测试你的知识:小测验
- 如何开始一个交互式解释器会话?
- 在哪里输入一个系统命令行来启动一个脚本文件?
- 说出保存在脚本文件中的代码的四种或更多的运行方式的名称?
- 说出在 Windows 上关于点击文件图标的两种陷阱的名称?
- 为什么可能需要重载模块?
- 如何从 IDLE 中运行脚本?
- 说出关于使用 IDLE 的两种陷阱的名称?
- 什么是命名空间,且它是如何和模块文件相关的?
测试你的知识:答案
- 如何开始一个交互式解释器会话?
<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">cd</font>
到 Python 安装的地方,或键入它的完整目录路径而不只是 python(比如,在 Windows 上是 C:\Python33\python,除非你正在使用 3.3 启动器)
- 在哪里输入一个系统命令行来启动一个脚本文件?
- 说出保存在脚本文件中的代码的 4 种或更多的运行方式?
<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">exec</font>
内置函数,和 IDE GUI 选择如 IDLE 的 Run->Run Module 菜单选项来运行。在 Unix 上,它们还可以用 #! 技巧作为可执行文件来运行,而且一些平台支持更特殊的启动技术(比如,拖拽)。另外,一些文本编辑器有运行 Python 代码的独特方式,一些 Python 程序被提供为独立运行的 “冰冻的二进制” 可执行文件,且一些系统在嵌入的模式中使用 Python 代码,在那里它被一个用像 C,C++ 或 Java 语言编写的封闭系统自动运行。这后一个技术通常被用来提供用户自定义层。
4. 说出在 Windows 上关于点击文件图标的两种陷阱?打印然后退出的脚本在你可以查看输出前就让输出文件立即消失(这就是为什么
<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">input</font>
技巧派上用场的原因);被脚本产生的错误消息也会出现在一个输出窗口中,它在你可以检查它的内容前就会关闭(这是系统命令行和如 IDLE 这种 IDE 更适合大多数开发的原因之一)
这里说的只适合于 Windows,我也没测试过,在 Mac 上无法重现。
- 为什么可能需要重载模块?
- 如何从 IDLE 中运行脚本?
在希望运行的文件的文本编辑窗口中,选择窗口的 Run->Run Module 目录选项。这将窗口的源码作为顶层脚本文件来运行并在交互式 Python shell 窗口显示它的输出。 - 说出关于使用 IDLE 的两种陷阱?
- 什么是命名空间,且它是如何和模块文件相关的?
测试你的知识:Part I 练习
是时候开始自己编写一点代码了。这第一套练习相当简单,但旨在为阅读本书余下部分做好准备,而且它的一些问题暗示了后面章节中接下来的主题。 确保到附录 D 的 Part I 查看答案;这些练习和它们的答案有时包含了正文中没有讨论到的额外信息,所以即使你成功的独立回答出了所有问题,也应该看一下这些答案。- 交互。 使用系统命令行,IDLE,或在你平台上适用的任何其他方法,来开启 Python 交互式命令行(>>> 提示符),然后输入表达式 “Hello World!”(包括双引号)。这个字符串应该对你回显出来。
<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">cd</font>
shell 命令,键入 Python 可执行文件的完整路径,或把它的路径添加到你的 PATH 环境变量中。
如果想的话,在 Unix 系统上可以将 PATH 设置到 .cshrc 或 kshrc 文件中来让 Python 永远可用;在 Windows 上要达到这个效果,环境变量 GUI 通常就是你想要的。参见附录 A 来获取关于环境变量设置的帮助。
- 程序。使用你选择的文本编辑器,编写一个含有单一语句
<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">print('Hello module world!')</font>
的简单模块文件并且将它存储为 module1.py。
<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">python module1.py</font>
),内置 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">exec</font>
调用,导入与重载,诸如此类。
事实上,尽你所能的使用尽可能多的本章讨论过的启动技术,通过运行文件来实验。哪一种技术看起来最简单?(当然,这个问题没有正确答案)
- 模块。开启 Python 交互式命令行(>>> 提示符)然后导入你在练习 2 中编写的模块。
<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">__pycache__</font>
子目录中有类似的东西?)
—拖回来可以,否则不能run 无
- 脚本。如果你的平台支持,在 module1.py 文件的顶部添加 #! 行,给此文件可执行的权限,然后作为可执行文件直接运行。
- 错误和调试。在 Python 交互式命令行,输入数学表达式和赋值语句来实验。在这个过程中,输入表达式 2 500 和 1 / 0**,然后像我们在本章之前做的那样引用一个未定义的变量名。发生了什么?
- 中断和循环。在 Python 命令行,输入:
发生了什么?在 Python 所有最近的版本中,你将看到一个我们将在答案附录中描述的奇怪输出,而且它会在我们在本书的下一部分中学习引用时更加有意义。如果你正在使用老于 1.5.1 的 Python 版本,在大多数平台上,一个 Ctrl-C 组合键很可能会有帮助。你认为为什么你的 Python 版本会以它对这段代码响应的方式那样去响应?
L = [1, 2] # 创建一个两个项目的列表
L.append(L) # 将L作为单独的一项添加给自己
L # 打印L:一个循环的对象
警告
如果你确实有一个老于版本 1.5.1 的 Python(但愿今天很少出现这种情况!),在运行这个测试前,确保你的机器使用 Ctrl-C(或其他类似)的组合键可以停止程序,否则你可能需要等待很长一段时间。- 文档。在继续前进前,花至少 15 分钟浏览 Python 库和语言手册来了解标准库中的可用工具和文档集的结构。至少要花这么长的时间来熟悉手册集合中主要主题的位置;一旦熟悉后,要找到所需要的东西就很容易了。
<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">help</font>
函数)。如果你还有时间,去探索 Python 网站,和它的 PyPi 第三方扩展仓库。特别是检查一下 Python 官网文档和搜索页;它们可是非常重要的资源。
测试你的知识:Part I 练习 —— 答案
是时候开始自己编写一点代码了。这第一套练习相当简单,但旨在让你为阅读本书余下部分做好准备,而且它的一些问题暗示了后面章节中接下来的主题。确保到附录 D 的 Part I 查看答案;这些练习和它们的答案有时包含了正文中没有讨论到的额外信息,所以即使你成功的独立回答出了所有问题,你也应该看一下这些答案。交互
使用系统命令行,IDLE,或在你平台上适用的任何其他方法,来开启 Python 交互式命令行(>>> 提示符),然后输入表达式 “Hello World!”(包括双引号)。这个字符串应该对你回显出来。这个练习的目的是让你配置好运行 Python 的环境。在一些场景中,你可能需要首先运行一个<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">cd</font>
shell 命令,键入 Python 可执行文件的完整路径,或把它的路径添加到你的 PATH 环境变量中。如果想的话,在 Unix 系统上你可以将 PATH 设置到你的 .cshrc 或 kshrc 文件中来让 Python 永远可用;在 Windows 上要达到这个效果,环境变量 GUI 通常就是你想要的。参见附录 A 来获取关于环境变量设置的帮助。
% python
...copyright information lines...
>>> "Hello World!"
'Hello World!'
>>> # Use Ctrl-D or Ctrl-Z to exit, or close window
程序
使用你选择的文本编辑器,编写一个含有单一语句<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">print('Hello module world!')</font>
的简单模块文件并且将它存储为 module1.py。现在,通过使用任何你喜欢的启动选项来运行这个文件:在 IDLE 中运行它,点击它的文件图标,在系统 shell 的命令行上将其传递给 Python 解释器(比如,<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">python module1.py</font>
),内置 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">exec</font>
调用,导入与重载,诸如此类。事实上,尽你所能的使用尽可能多的本章讨论过的启动技术,通过运行文件来实验。哪一种技术看起来最简单?(当然,这个问题没有正确答案)
module1.py
print('Hello module world!')
% python module1.py
Hello module world!
模块
开启 Python 交互式命令行(>>> 提示符)然后导入你在练习 2 中编写的模块。尝试将文件移动到不同的目录然后从它的原始目录再次导入(也就是说,当你导入时在原始目录运行 Python,也就是说先退出 Python shell)。发生了什么?(提示:在原始目录中是不是仍然有一个 module1.pyc 的字节码文件,或在那里的<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">__pycache__</font>
子目录中有类似的东西?)
% python
>>> import module1
Hello module world!
>>>
测试:将 module1.py 移动到 ./testdir 子目录,然后再次导入会发生什么?
再次导入:
mv module1.py testdir/
会发现出错,发现原始目录中并没有 module1.pyc 的字节码文件,而是在
% python
>>> import module1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'module1'
>>>
<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">__pycache__</font>
子目录中有 module1.cpython-310.pyc 这个文件。
这个现象说明了什么问题?
这个现象说明,在导入 Python 模块时,Python 会搜索<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">sys.path</font>
中的路径,如果找不到该模块,就会引发 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">ModuleNotFoundError</font>
错误。在这种情况下,将模块移动到子目录后,Python 无法在 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">sys.path</font>
中找到该模块,因此导入模块时会出错。
要解决这个问题,需要在代码中添加以下语句,以确保子目录包含在 <font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">sys.path</font>
中:
然后,可以再次尝试导入模块:
import sys
sys.path.append('testdir')
% python
>>> import module1
Hello module world!
>>>
脚本
如果你的平台支持,在 module1.py 文件的顶部添加 #! 行,给此文件可执行的权限,然后作为可执行文件直接运行。第一行需要包含什么?#! 通常只在 Unix,Linux 和类 Unix 系统如 Mac OS X 上有意义;如果你工作在 Windows 上,尝试通过在一个命令提示符窗口,只列出它的名字而不需要单词 “Python” 在它的前面来运行文件(这在最新版本的 Windows 上适用),或通过 Start->Run… 对话框,或类似的方法。如果你正在使用 Python3.3 或和它一起安装的 Windows 启动器,尝试修改脚本的 #! 行来启动可能已经安装到电脑上的不同的 Python 版本(或等价地,完成附录 B 中的教程) 编辑 module1.py:
#!/usr/bin/env python
print('Hello module world!')
% chmod +x module1.py
% ./module1.py
Hello module world!
错误和调试
在 Python 交互式命令行,输入数学表达式和赋值语句来实验。在这个过程中,输入表达式<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">2 ** 500</font>
和 1 / 0,然后像我们在本章之前做的那样引用一个未定义的变量名。发生了什么?
你可能还不知道,但当你犯错误时,你就正在进行异常处理(将在 Part VII 中深入探索的主题)。技术上讲你正在触发所谓的默认异常处理程序 —— 打印一个标准错误信息的逻辑。如果你没有捕获错误,默认的处理程序就会去捕获然后在响应中打印出标准的错误信息。
在 Python 中,异常也和调试的概念绑定在一起。当你首次开始学习时,Python 的关于异常的默认错误消息将尽可能多地提供你所需要的错误处理支持 —— 它们给出了错误的原因,和显示出当错误发生时正在被执行的代码行。要获取更多关于调试的信息,参见侧边栏 调试 Python 代码。
% python
>>> 2 ** 500
3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589376
>>> 1/ 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
>>> spam
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'spam' is not defined
>>>
中断和循环
在 Python 命令行,输入:发生了什么?在 Python 所有最近的版本中,你将看到一个我们将在答案附录中描述的奇怪输出,而且它会在我们在本书的下一部分中学习引用时更加有意义。如果你正在使用老于 1.5.1 的 Python 版本,在大多数平台上,一个 Ctrl-C 组合键很可能会有帮助。你认为为什么你的 Python 版本会以它对这段代码响应的方式那样去响应?
L = [1, 2] # 创建一个两个项目的列表
L.append(L) # 将L作为单独的一项添加给自己
L # 打印L:一个循环的对象
警告
如果你确实有一个老于版本 1.5.1 的 Python(但愿今天很少出现这种情况!),在运行这个测试前,确保你的机器使用 Ctrl-C(或其他类似)的组合键可以停止程序,否则你可能需要等待很长一段时间。
% python
>>> L = [1,2]
>>> L.append(L)
>>> L
[1, 2, [...]]
>>>
文档。
在继续前进前,至少花 15 分钟浏览 Python 库和语言手册来了解标准库中的可用工具和文档集的结构。至少要花这么长的时间来熟悉手册集合中主要主题的位置;一旦熟悉后,要找到所需要的东西就很容易了。可以通过在一些 Windows 上的 Python 开始按钮入口,或在 IDLE 的帮助下拉菜单中的 Python Docs 选项,或在线的 http://www.python.org/doc 来查找这个手册。在第 15 章还将讲述更多关于手册和其他可用文档资源(包括 PyDoc 和<font style="color:rgb(133, 128, 128);background-color:rgb(249, 250, 250);">help</font>
函数)。如果还有时间,去探索 Python 网站,和它的 PyPi 第三方扩展仓库。特别是检查一下 Python 官网文档和搜索页;它们可是非常重要的资源。