Python 源码剖析之基础知识
为了和《Python 源码剖析》一书保持一致,本系列笔记分析的源码是 cpython-2.5.6 。
Python 总体架构
Python 的总体架构可以分成三个主要的部分:
大量的核心模块、库和用户自定义模块
Python 作为脚本语言的核心即解释器(词法分析产生 token,语法分析建立抽象语法树,编译成字节码,虚拟机执行字节码)
Python 运行时环境(对象和类型体系,内存分配器,运行时状态信息)
Python 总体架构
Python 源代码组织结构
为了和参考书籍保持一致,便于学习,这里仍旧采用 cpython-2.5.6 进行研究学习。
源代码目录如下:
├── Demo
├── Doc
├── Grammar
├── Include
├── LICENSE
├── Lib
├── Mac
├── Makefile.pre.in
├── Misc
├── Modules
├── Objects
├── PC
├── PCbuild
├── PCbuild8
├── Parser
├── Python
├── README
├── RISCOS
├── Tools
├── configure
├── configure.in
├── install-sh
├── pyconfig.h.in
└── setup.py
其中:
Include: Python 提供的所有 C 语言头文件,当自己想用 C 或 C++ 来编写自定义模块扩展 Python 的时候,就需要用到这些头文件。可以看到里面有我们之后要研究的各种对象的声明。
➜ cpython-2.5 tree -L 1 Include
Include
├── Python-ast.h
├── Python.h
├── abstract.h
├── asdl.h
├── ast.h
├── bitset.h
├── boolobject.h
├── bufferobject.h
├── cStringIO.h
├── cellobject.h
├── ceval.h
├── classobject.h
├── cobject.h
├── code.h
├── codecs.h
├── compile.h
├── complexobject.h
├── datetime.h
├── descrobject.h
├── dictobject.h
├── enumobject.h
├── errcode.h
├── eval.h
├── fileobject.h
├── floatobject.h
├── frameobject.h
├── funcobject.h
├── genobject.h
├── graminit.h
├── grammar.h
├── import.h
├── intobject.h
├── intrcheck.h
├── iterobject.h
├── listobject.h
├── longintrepr.h
├── longobject.h
├── marshal.h
├── metagrammar.h
├── methodobject.h
├── modsupport.h
├── moduleobject.h
├── node.h
├── object.h
├── objimpl.h
......
├── pythread.h
├── rangeobject.h
├── setobject.h
├── sliceobject.h
├── stringobject.h
├── structmember.h
├── structseq.h
├── symtable.h
├── sysmodule.h
├── timefuncs.h
├── token.h
├── traceback.h
├── tupleobject.h
├── ucnhash.h
├── unicodeobject.h
└── weakrefobject.h
0 directories, 80 files
Lib: Python 自带的所有标准库,都是用 Python 语言编写的。可以看到有我们经常使用的类似于 base64,os 这样的 Python 标准库
➜ cpython-2.5 tree -L 1 Lib
Lib
├── BaseHTTPServer.py
├── Bastion.py
├── CGIHTTPServer.py
...
├── base64.py
...
├── hashlib.py
├── heapq.py
...
├── md5.py
...
├── optparse.py
├── os.py
├── os2emxpath.py
├── pdb.doc
├── pdb.py
├── pickle.py
├── pickletools.py
...
├── random.py
├── re.py
├── repr.py
...
├── socket.py
├── sqlite3
...
├── subprocess.py
...
├── xml
├── xmllib.py
├── xmlrpclib.py
└── zipfile.py
39 directories, 193 files
Modules: 该目录也是包含了 Python 自带的的模块,和 Lib 目录不同的是,Modules 下的模块都是用 C 语言编写的,是那些对速度要求非常严格的模块。比如时间相关的 datetime,timeing 等模块
➜ cpython-2.5 tree -L 1 Modules
Modules
├── Setup.config.in
├── Setup.dist
...
├── _randommodule.c
├── _sqlite
...
├── cPickle.c
├── cStringIO.c
...
├── datetimemodule.c
...
├── getpath.c
...
├── md5.c
├── md5.h
├── md5module.c
...
├── python.c
├── readline.c
├── resource.c
...
├── timemodule.c
├── timing.h
├── timingmodule.c
...
├── zipimport.c
├── zlib
└── zlibmodule.c
5 directories, 121 files
Parser: 该目录包含了 Python 解释器中的 Scanner 和 Parser 部分(词法分析和语法分析),还包含类似于 YACC 这样的能根据 Python 语言的语法自动生成 Python 语言的文法和词法分析器的工具。
➜ cpython-2.5 tree -L 1 Parser
Parser
├── Python.asdl
├── acceler.c
├── asdl.py
├── asdl_c.py
├── bitset.c
├── firstsets.c
├── grammar.c
├── grammar.mak
├── grammar1.c
├── intrcheck.c
├── listnode.c
├── metagrammar.c
├── myreadline.c
├── node.c
├── parser.c
├── parser.h
├── parsetok.c
├── pgen.c
├── pgenmain.c
├── printgrammar.c
├── spark.py
├── tokenizer.c
├── tokenizer.h
└── tokenizer_pgen.c
0 directories, 24 files
Objects: 和 Include 目录对应,这个目录包含了所有 Python 的内建对象 C 语言实现代码,还包含了 Python 在运行时需要的所有的内部使用对象的实现。
➜ cpython-2.5 tree -L 1 Objects
Objects
├── abstract.c
├── boolobject.c
├── bufferobject.c
├── cellobject.c
├── classobject.c
├── cobject.c
├── codeobject.c
├── complexobject.c
├── descrobject.c
├── dictnotes.txt
├── dictobject.c
├── enumobject.c
├── exceptions.c
├── fileobject.c
├── floatobject.c
├── frameobject.c
├── funcobject.c
├── genobject.c
├── intobject.c
├── iterobject.c
├── listobject.c
├── listsort.txt
├── longobject.c
├── methodobject.c
├── moduleobject.c
├── object.c
├── obmalloc.c
├── rangeobject.c
├── setobject.c
├── sliceobject.c
├── stringlib
├── stringobject.c
├── structseq.c
├── tupleobject.c
├── typeobject.c
├── unicodectype.c
├── unicodeobject.c
├── unicodetype_db.h
└── weakrefobject.c
1 directory, 38 files
Python: 该目录包含了 Python 解释器中的 Compiler 和执行引擎部分,是 Python 运行的核心所在。
➜ cpython-2.5 tree -L 1 Python
Python
├── Python-ast.c
├── asdl.c
├── ast.c
├── atof.c
├── bltinmodule.c
├── ceval.c
├── codecs.c
├── compile.c
├── dup2.c
├── dynload_aix.c
├── dynload_atheos.c
├── dynload_beos.c
├── dynload_dl.c
├── dynload_hpux.c
├── dynload_next.c
├── dynload_os2.c
├── dynload_shlib.c
├── dynload_stub.c
├── dynload_win.c
├── errors.c
├── fmod.c
├── frozen.c
├── frozenmain.c
├── future.c
├── getargs.c
├── getcompiler.c
├── getcopyright.c
├── getcwd.c
├── getmtime.c
├── getopt.c
├── getplatform.c
├── getversion.c
├── graminit.c
├── hypot.c
├── import.c
├── importdl.c
├── importdl.h
├── mactoolboxglue.c
├── marshal.c
├── memmove.c
├── modsupport.c
├── mysnprintf.c
├── mystrtoul.c
├── pyarena.c
├── pyfpe.c
├── pystate.c
├── pystrtod.c
├── pythonrun.c
├── sigcheck.c
├── strdup.c
├── strerror.c
├── strtod.c
├── structmember.c
├── symtable.c
├── sysmodule.c
├── thread.c
├── thread_atheos.h
├── thread_beos.h
├── thread_cthread.h
├── thread_foobar.h
├── thread_lwp.h
├── thread_nt.h
├── thread_os2.h
├── thread_pth.h
├── thread_pthread.h
├── thread_sgi.h
├── thread_solaris.h
├── thread_wince.h
└── traceback.c
0 directories, 69 files
修改 Python 源代码并编译安装
为了观察 Python 的执行过程,我们经常需要修改 Python 源代码,改变一些执行逻辑,添加一些日志输出,然后重新编译安装 Python 并运行观察验证结果。编译安装可以按照以下步骤:
./configure --prefix=$(pwd)
make && make install
注意,我在 Mac OS X Yosemite 10.10.3 上编译失败了,日志显示:
➜ cpython-2.5 make
gcc -c -fno-strict-aliasing -Wno-long-double -no-cpp-precomp -mno-fused-madd -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I. -IInclude -I./Include -DPy_BUILD_CORE -o Modules/python.o ./Modules/python.c
clang: error: unknown argument: '-mno-fused-madd'
make: *** [Modules/python.o] Error 1
gcc 识别不了相应的一个 编译参数,搜索了一下,原因应该是 XCode 的版本和当时的 2.5.6 不兼容,所以果断选择了在 Ubuntu 14.04 上编译安装 Python,很快就通过了。