Python 的角度 —— 字节码编译

未匹配的标注

当你执行一个程序时,Python会在内部且对你是几乎透明的情况下编译你的源码(文件中的语句)为一种名为字节码的格式。编译仅仅是一个翻译步骤,且字节码是源码的更底层且与平台无关的展示。大致的讲,Python通过将每一条源码语句分解为独立步骤,将它们翻译为一组字节码指令。执行这个字节码翻译是为了提高执行速度——字节码能比在文本文件中的源码语句运行得快得多。

你将注意到:在前面的段落中说了这个过程是对你是几乎透明的。如果Python进程在你的机器上有写权限,它就会把程序的字节码存储到以 .pyc 的扩展名(".pyc" 意味着编译的“.py” 源)结尾的文件中。

在Python 3.2之前,你会看到在你已经运行了一些程序后,这些文件和对应的源代码文件一起出现在你的电脑上——也就是,同样的目录中。比如,你将注意到:在导入 script.py 后会有一个 script.pyc

在 3.2 及之后,Python 将 其 .pyc 字节码文件保存在你的源码文件所处目录的一个名为__pycache__ 的子目录中,并且在那些名称就可以识别出创建它们的Python版本的文件中(比如,script.cpython-33.pyc)。这个新的 __pycache__子目录是用来避免混乱的,并且字节码文件的新的命名约定避免了安装在同一个电脑上的不同Python版本覆盖其他版本保存的字节码。尽管这些字节码文件模型对于大多数Python程序来说是自动和无关的,而且在前面描述过的不同Python实现中都有很大不同,但我们还是会在第22章更深入研究它们。

在两种模型中,Python都保存像这样的字节码来作为启动速度优化。只要自从字节码上一次保存起,你没有修改过源码且没有使用不同于创建字节码的Python运行源码,下一次运行程序时,Python将加载 .pyc 文件且跳过编译步骤。它工作如下:

  • 源更改:Python 自动检查源和字节码文件的最后修改时间戳来知道什么时候必须重新编译——如果你编辑并重新保存了源码,字节码在下一次运行程序时就会自动重新创建。
  • Python 版本:导入也会通过一些方法来检查来看是否文件必须被重新编译——因为它由一个不同的Python版本创建。在3.2和更早版本中,使用的是用字节码文件中的“魔术”版本号,或在3.2和之后版本中,使用的是字节码文件名中的信息。

结果是源码更改和Python版本号不同都会触发创建一个新的字节码文件。如果Python不能将字节码文件写到机器上,那么程序仍然可运行——字节码会被产生在内存中并在程序退出时简单的被丢弃。然而,因为 .pyc 文件加快了启动速度,对大的程序你会想确保它们被写入。字节码文件还是一种发布Python程序的方法——如果Python只发现了 .pyc 文件,即使原来的 .py 源文件不存在,它也会很乐意执行这个程序。(要参考另一种发布选项,请参见 冻结的二进制文件。)

最后,记住仅对于那些被导入的文件,字节码才会被保存到文件中,而不是那些只被作为脚本运行的程序的顶层文件(严格来说,它是一个导入优化)。我们将在第3章中探索导入基础,然后在第五部分深入学习导入。而且,对每一个程序运行,一个指定的文件只会被导入(和可能被编译)一次,并且在交互式提示符——一个我们将在第3章中学习的编程模式——那里被键入的代码将永远不会被保存为字节码。

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~