1. 2005-12-17 Python源码剖析.1

1.1. 编译Python

1.1.1. Python总体架构

  • 在最高的层次上,Python的整体架构可以分为四个主要的部分,整个架构如图1所示。在左边,是Python提供的大量的模块,库以及用户自定义的模块。比如在执行import os时,这个os就是Python内建的模块,当然用户还可以通过自定义模块来扩展Python系统。在本系列文章中,我们不会对这一部分进行过多的考察。
  • 在图的右边,是Python的运行时环境,包括对象/类型系统(Object/Type structures),内存分配器(Memory Allocator)和运行时状态(Current State of Python)。运行时状态维护了解释器在执行字节码时在不同的状态之间切换的动作,我们可以将它视为一个巨大而复杂的有穷状态机。内存分配器则全权负责Python中创建对象时对内存的申请工作,实际上它就是Python运行时与C中malloc的一层接口。而对象/类型系统则包含了Python中存在的各种内建对象,比如整数,list和dict等等
  • 在中间的部分,可以看到Python的核心,解释器(interpreter)。在解释器中,箭头的方向指示了Python运行时的数据流方向。其中Scanner对应词法分析,将文件输入的Python源代码或从命令行输入的一行行Python代码切分为一个一个的token;Parser对应语法分析部分,在Scanner的分析结果上进行语法分析,建立抽象语法树(AST);Compiler是根据建立的AST生成指令集合——Python字节码(byte code),就像Java编译器和C#编译器所做的那样;最后由Code Evaluator来解释并执行这些字节码。因此,Code Evaluator又可以被称为执行引擎。
  • 图中,在Interpreter与右边的对象/类型系统,内存分配器之间的箭头表示“使用”关系;而与运行时状态之间的箭头表示修改关系,即Python在执行的过程中会不断地修改当前解释器所处的状态,在不同的状态之间切换。

1.1.2. Python源代码的组织

  • 中国有句老话,巧妇难为无米之炊。要分析Python源码,首先当然要获得Python源码。Python源码可以从Python的官方网站http://www.python.org自由下载。当前Python的最新版本是2.4.2,在本书中,我采用的是Python2.4.1:

下载了Python的源代码压缩包并解压后,可以看到如图3所示的目录结构。

  1. Include :该目录下包含了Python提供的所有头文件,如果用户需要自己用C或C++来编写自定义模块扩展Python,那么就需要用到这里提供的头文件。
  2. Lib :该目录包含了Python自带的所有标准库,Lib中的库都是用Python语言编写的。
  3. Modules :该文件夹中包含了所有用C语言编写的模块,比如ramdom,cStringIO等,Modules中的模块是那些对速度要求非常严格的模块。而有一些对速度没有太严格要求的模块,比如os,就是用Python编写,并且放在Lib目录下。
  4. Parser :Parser目录中包含了Python解释器中的Scanner和Parser部分,即对Python源代码进行词法分析和语法分析的部分。除了这些,Parser目录下还包含了一些有用的工具,这些工具能够根据Python语言的语法自动生成Python语言的词法和语法分析器,与YACC非常类似。
  5. Objects :该目录中包含了所有Python的内建对象,包括整数,list,dict等;同时,该目录还包括了Python在运行时需要的所有的内部使用对象的实现
  6. Python :该目录下包含了Python解释器中的Compiler和执行引擎部分,是Python运行的核心所在。
  7. PCBuild :包含了Visual Studio 2003工程文件,研究Python源代码就从这里开始。

1.1.3. 编译Python

  • 好了,下载了Python的源代码之后,我们就可以走出剖析Python源码的第一步——编译Python——了:)
  • Python2.4.1是在Visual Studio 2003环境下开发的,在PCBuild目录下可以看到VS2003的工程文件,打开工程后,还需要进行一些设置,才能成功编译。
  • 首先,我们需要激活VS2003的配置对话框:
  • 在配置对话框中,首先要做的就是更改Startup Project,Python2.4.1中默认设置的是_bsddb,我们需要将其改为Python。
  • 由于我们剖析的只是Python的核心部分,不会涉及到工程中的一些标准库和其他的模块,所以我们需要将它们从编译的列表中删除。点击配置对话框左边列表框中的“Configuration Properties”后,会出现当前配置为需要编译的子工程,取消多余的子工程的选中状态,只保留pythoncore和python的选中状态。
  • 需要进行的改动就是这么多了,但是完成这些改动后,如果马上开始编译,那么编译还是会失败:
  • 原因是我们还需要一个pythonnt_rc_d.h,这个文件在Python2.4.1的源码包中没有提供,必须要通过一个编译make_versioninfo子工程才能自动生成:

好了,现在再编译,一切都会顺利完成了。