第二章 Python如何运行程序
本章我们将学习,Python解释器通常是如何执行程序的
Python解释器简介
当你编写了一段Python程序,解释器将读取程序,并按照其中的命令执行,得出结果。实际上,解释器是代码与机器的计算机硬件之间的软件逻辑层。
当Python软件包安装在机器上后,他会生成一些组件:至少包括一个解释器和一套支持库
程序执行
程序员视角
一个Python程序仅是一个包含Python语句的文本文件
你可以用任何自己喜欢的文本编辑器创建Python语句组成的文件;按照惯例,python文件是以.py结尾的。从技术上来讲,这种命名方案在被“导入”时才是必须的,但是绝大多数python文件为了统一都是以.py命名的
Python的视角
在代码开始处理之前,python还会执行一些步骤。确切地说,第一步是编译成所谓的“字节码”,之后将其转发到所谓的“虚拟机”中
字节码编译
编译——Python通过把你的每一条源语句分解为单一步骤来翻译成一组字节码指令。(字节码运行速度快很多)
- 如果Python进程有机器写入权限,会把字节码保存为.pyc文件(3.2版本以后,保存在__pycache__子目录中)
- 这样保存字节码是作为对启动速度的一种优化;下次运行程序时,如果期间没有修改过源代码,并且运行使用的是同一个python编译器版本,那么python将会加载.pyc文件并跳过编译这个步骤:
- 源文件的改变:自动检查源文件和字节码文件最后一次修改的时间戳
- Python的版本:导入机制同时检查是否需要因为使用了不同的python版本而重新编译(3.2之前版本信息保存在.pyc文件中,3.2之后保存在.pyc文件名中)
- 如果无法在机器上写入文件,字节码会在内存中生成,并在程序结束时直接被丢弃
- 字节码文件同样是发布python程序的方法之一:如果只有pyc,python也可以运行该程序
- 字节码只会针对哪些被导入的文件而生成,而不是顶层的执行脚本(严格来说,是一种针对导入的优化);文件仅在程序运行(或可能编译)时才会被导入,而且在交互式命令行中输入的命令不会生成字节码
Python虚拟机(PVM)
一旦程序编译成字节码,之后的字节码发送到PVM程序上来执行。
PVM不是一个独立的程序,不需要安装;本质上,就是迭代运行字节码指令的一个大循环,一个接一个地完成操作。
PVM是Python的运行时引擎,时常表现为Python系统的一部分,并且是实际运行脚本的组件。
从技术上讲,是作为python解释器的最后一步
性能的含义
区别于传统语言:
- python工作中通常没有构建或者“make”的步骤:代码在写好之后立即运行;
- python字节码不是机器的二进制代码,是特定于Python的一种表现形式
这就是python无法运行的像C、C++一样快的原因,PVM仍需解释字节码,并且字节码指令比CPU指令需要更多的工作;
python区别于还需内部编译的经典解释器,并不需要反复重新分析、分解每一行源代码;
所以结果是——纯python的运行速度介于传统的编译语言和传统的解释语言之间
开发的含义
python执行模型导致的结果是其开发和执行的环境实际上并没有区别
动态语言——我们在python中真正拥有的只有运行时:完全不需要初始的编译阶段,所有的事情都是在程序运行时发生的
执行模型的变体
一些针对图2-2的变体
Python的各种实现
主要有5种——Cpython、Jython、IronPython、Stackless、PyPy;还包括Cython、Shed Skin
Cpython是标准的实现,也是大多数读者将选择使用的(也是本书的版本);PyPy是一个现成的CPython的替代品,可以更快地运行大多数程序;Jython和IronPython是完全独立的Python实现,能够提供直接的Java和.NET组件的使用接口;Jython和IronPython通过提供Python语言更完整的解决方案
Cpython:标准的Python
就是从www.python.org获取的,以及绝大多数机器自动安装的;参考图2-2
Jython:基于Java的Python
目的是与Java编程语言集成,包含Java类,这些类将Python源代码编译成Java字节码,并将得到的字节码定向到JVM上;本质是将图2-2的后两步替换为基于Java的等效实现
解决了希望寻找一门作为前端脚本语言的Java开发者的诉求
http://jython.org
IronPython:基于.NET的Python
目的是让Python程序可以与Windows平台上的.NET框架以及与之对应的Linux上开源的Mono编写成的应用相集成;本质是将图2-2的后两步替换为基于.NET的等效实现(与Jython是一个创始人)
http://ironpython.net
Stackless:注重并发的Python
标准CPython针对并发性而优化的一个增强版实现,促进了协程的出现
http://stackless.com
PyPy:注重速度的Python
是Cpython标准的另一个实现,更注重性能,提供了一个带有即时编译器(JIT)的python的快速实现
将字节码的部分直接转换成运行速度更快的二进制机器码,而且发生在程序运行的时候
PyPy能够运行大多数的Cpython代码
动态优化下,甚至有时候运行速度超越C;在算法密集和计算密集程序中尤为明显
执行优化工具
Cython、Shed Skin、Psyco
冻结二进制文件
冻结二进制文件以支持在未安装python的环境中运行
py2exe、PyInstaller、py2app、freeze、cx_freeze
冻结二进制文件与真实的编译器输出结果有所不同:通过虚拟机运行字节码。但是运行速度和最初的源代码程序相同
未来的可能性
parrot、unladen swallow
《Python学习手册(第五版)》学习随记