第2章:Python如何运行程序

python

Python解释器简介

"""

解释器是一种让其它程序运行起来的程序。当你编写了一段python程序,python解释器将读取程序,并按照其中的命令执行,得出结果。实际上,解释器是代码与机器的计算机硬件之间的软件逻辑层。

当python包安装在机器上后,它会生成一些组件:至少包括一个解释器和一套支持库。编写的python代码必须在解释器中运行。

"""

程序执行

程序员的视角

"""

一个python程序仅是一个包含python语句的文本文件。

例如,下面这个命名为script0.py的文件,

"""

print(\'hello world\')

print(2 ** 100)

"""

这个文件包含了两个python print语句,在输出流中简单地打印一个字符串和一个数学表达式的结果。当你将这些语句输入到文本文件后,必须告诉python去执行这个文件。也就是说,从头至尾按照顺序一个接一个地运行文件中的语句。

"""

python的视角

"""

当python运行脚本时,在代码开始进行处理之前,python还会执行一些步骤。确切地说,第一步是编译成所谓的\'字节码\',之后将其转发到所谓的\'虚拟机\'中。

"""

字节码编译

"""

执行程序时,python内部会先将源代码编译成所谓字节码的形式。概括地说,python通过把你的每一条源语句分解为单一步骤来翻译成一组字节码指令。这些字节码可以提高执行速度。比起文本文件中原始的源代码语句,字节码的运行速度要快得多。

如果python进程在机器上拥有写入权限,那么它将把程序的字节码保存为一个以.pyc为扩展名的文件(.pyc就是编译过的.py源代码)。在python3.2以及之后的版本,python将把.pyc字节码存储在名为__pycache__的子目录中,这个子目录位于与源文件相同的路径下。

在上述两种字节码文件模型中,python这样保存字节码是作为对启动速度的一种优化。下一次运行程序时,如果你在上次保存字节码之后没有修改过源代码,并且运行使用的是同一个python编译器版本,那么python将会加载.pyc文件并跳过编译这个步骤。这个过程的工作原理如下:

  - 源文件的改变:python会自动检查源文件和字节码文件最后一次修改的时间戳,确认它是否必须重新编译;如果你编译后又保存了源代码,下次程序运行时,字节码将自动重新创建。

  - python的版本:导入机制同时检查是否需要因为使用了不同的python版本而重新编译,这些版本信息在python3.2版本之前存储在字节码文件中,而在3.2版本及之后,存储在字节码文件名中(例如:script.cpython-33.pyc)。

其结果就是源文件的修改和python版本的改变都会触发新的字节码文件的编译。如果python无法在机器上写入字节码,程序仍然可以工作;字节码会在内存中生成,并在程序结束时直接被丢弃。字节码文件同样是发布python程序的方法之一:如果python找到的都是.pyc文件,它也很乐意运行这个程序,即便没有原始的.py源代码文件。
字节码只会针对那些被导入(import)的文件而生成,而不是顶层的执行脚本(严格来说,这是一种针对\'导入\'的优化)。文件仅在程序运行(或者可能编译)时才会被导入,而且在交互式命令行中输入的命令不会生成字节码。

"""

python虚拟机(PVM)

"""

一旦程序编译成字节码(或字节码从已经存在的.pyc文件中载入),之后的字节码发送到通常称为python虚拟机(python virtual machine,简写为PVM)的程序上来执行。

本质上,PVM就是迭代运行字节码指令的一个大循环,一个接一个地完成操作。PVM是python的运行时引擎,它时常表现为python系统的一部分,并且是实际运行脚本的组件。

字节码的编译是自动完成的,而且PVM也仅仅是安装在机器上的python系统的一部分。

"""

性能的含义

"""

熟悉C和C++的,或许已经发现了python模式中的一些不同之处。其中之一是,在python的工作中通常没有构建或\'make\'的步骤:代码在写好之后立即运行。还有一个就是,python字节码不是机器的二进制代码(例如Intel或ARM芯片的指令)。字节码是特定于python的一种表现形式。

这就是python代码无法运行的像C或C++代码一样快的原因,PVM循环(而不是CPU芯片)仍需解释字节码,并且字节码指令比CPU指令需要更多的工作。另一方面,与其他经典的解释器不同,这里仍有内部的编译步骤:python并不需要反复地重新分析和重新分解每一行源代码语句的文本。最终的效果就是纯python代码的运行速度介于传统的编译语言和传统的解释语言之间。

"""

开发的含义

"""

python执行模型所导致的另一个结果是其开发和执行的环境实际上并没有区别。也就是说,编译和执行源代码的系统是同一个系统。这将大大缩短开发周期。

"""

执行模型的变体

python的各种实现

"""

python语言有5种主要实现方式:CPython、Jython、IronPython、Stackless、PyPy。

CPython是标准的实现。

"""

CPython:标准python

"""

当你要与python的其它实现方式进行区分时,最初的、标准的python实现方式通常称作cpython(或者也可以直接称为python)。这就是你从http://www.python.org获取的,从ActivePython和Enthought的发行版中得到的,以及从绝大多数Linux和mac os x机器上自动安装的python。上图反映了cpython的运行时体系结构。

"""

Jython:基于Java的python

"""

jython系统是一种python语言的可选实现方式,其目的是与Java编程语言集成。jython包含Java类,这些类将python源代码编译成Java字节码,并将得到的字节码定向到Java虚拟机(JVM)上。仍然可以像平常一样,在文本文件中编写python语句;jython系统的本质是将上图最右边两个方框中的内容替换为基于Java的等效实现。

"""

IronPython:基于.NET的Python

"""

python的第三种实现方式是IronPython,在实现上,IronPython很像jython:它替换了上图最后的两个方框,将其换成.NET环境的等效执行方式。并且与jython一样。

"""

Stackless:注重并发的Python

"""

stackless python系统是标准cpython针对并发性而优化的一个增强版实现,因为stackless python不会在C语言调用栈上保存状态,这使得python更容易移植到较小的栈架构中,提供了更高效的多处理选项,并且促进了像协程这样的新的编程结构的出现。在stackless为python带来的所有优化中,微线程是python原生多线程工具的一个更高效和更轻量的替代品。微线程带来了更好的程序结构、更可读的代码以及更强的开发效率。

"""

PyPy:注重速度的python

"""

pypy系统是cpython标准的另一个实现,它更注重性能。它提供了一个带有即时编译器(just-in-time,JIT)的python快速实现,能够在安全环境中运行不信任代码的\'沙箱\'模型的工具,默认对stackless python系统的支持以及对大型并行需求的微线程支持。

pypy是原先的psyco即时编译器的继任者,并将psyco纳入一个追求速度的纯python实现。即时编译器事实上只是PVM的一个扩展(就是上图最右边的方框中所代表的),它将字节码中的部分直接转换成运行速度更快的二进制机器码。这一切发生在程序运行的时候,而非运行前的编译阶段。而且即时编译器能够通过追踪程序中的对象数据类型,创建针对python语言动态特性的机器代码。通过这种方式部分地替换字节码,程序将在运行的时候越跑越快。此外,一些python代码在pypy下运行也会占用更少的内存。

pypy能够运行大多数的cpython代码,尽管其中的C扩展模块通常必须重新编译,而且pypy有一些细小而微妙的语言特性差别,包括回避了一些常见编程模式的垃圾回收机制。例如,它的非引用计数方案意味着临时文件将不会立即被关闭或者从缓冲区中释放,而且甚至在某些情况下需要手动关闭。

"""

执行优化工具

Cython:python和C的混合体

"""

Cython系统(基于pyrex项目所完成的工作)是一种混合的语言,它为python代码配备了调用C函数以及使用变量、参数和类属性的C类型声明的能力。cython代码可以编译成使用python/C API的C代码,随后可以再完整地编译。尽管与python并不完全兼容,cython对于包装外部的C库以及提高python的C扩展的编码效率都很有用。

"""

Shed Skin:python到C++的转换器

"""

shed skin是一个新兴的系统,它采用了一种不同的python程序执行方法:尝试将python代码翻译成C++代码,然后使用机器中的C++编译器将得到的C++代码编译为机器代码。通过这种方式,它以一种平台无关的方式来运行python代码。

"""

Psyco:原先的即时编译器

"""

psyco系统并不是python的另一种实现方式,而是一个可以让程序运行的更快的扩展字节码执行模块组件。psyco是一个过时的项目。然后,它的思想被融入到前面介绍的更加完整的pypy系统中。

psyco是一个对PVM的增强工具,这个工具在程序运行时收集并使用类型信息,可以将部分程序的字节码转换成底层的真正的二进制机器代码,从而实现更快的执行速度。

"""

冻结二进制文件

"""

将python程序转为可执行程序,在python中被称作为冻结二进制文件(frozen binary)。这些程序可以不安装python环境而独立运行。

冻结二进制文件能够将程序文件的字节码、PVM(解释器)以及任何程序所需要的python支持文件捆绑在一起形成一个单独的文件包。这个文件包是一个单独的可执行二进制程序(例如,Windows系统中的.exe文件),如上图所示,这就好像将字节码和PVM混合在一起形成一个独立的组件----冻结二进制文件。

如今,有很多系统能够生成随平台特性而变化的冻结二进制文件:py2exe(为Windows平台提供了全面的支持)、PyInstaller(与py2exe类似,它能够在Linux及mac os x上使用,并且能够生成自安装的二进制文件)、py2app(创建mac os x应用程序)、freeze(最初的版本)和cx_freeze(同时提供python3.x和跨平台支持)。

冻结二进制文件与真实的编译器输出结果有所不同:他们通过虚拟机运行字节码。因此,除了必要的初始改进,冻结二进制文件和最初的源代码程序运行速度完全相同。冻结二进制文件并不小(他们包括了一个PVM),但是以目前的标准来衡量,他们的文件也不是特别大。因为在冻结二进制文件中嵌入了python,接收端不需要安装python来运行这些冻结二进制文件。此外,由于代码嵌入在冻结二进制代码之中,对于接收者来说,代码都是隐藏起来的。

"""

 

以上是 第2章:Python如何运行程序 的全部内容, 来源链接: utcz.com/z/387259.html

回到顶部