一、python的整体架构
python在执行的过程中,会不断地修改当前解释器所处的状态,在不同的状态之间切换。 解释器与右边的对象/类型系统、内存分配器之间的箭头表示“使用”关系,而与运行时状态之间的箭头表示“修改”关系。
1.1 File Group
内建模块、库、用户自定义模块
1.2 RuntimeEnvironment
运行时环境
1.2.1 Object/Type Structures
对象/类型系统,包含了python中存在的各种内建对象,比如整数、list和dict,以及各种用户自定义的类型和对象。
1.2.2 Memory Allocator
内存分配器,全权负责python中创建对象时,对内存的申请工作,实际上它就是python运行时与c中malloc的一层接口。
1.2.3 Current State of Python
运行时状态信息,维护了教室起在执行字节码时不同的状态之间切换的动作,我们可以将它视为一个巨大而复杂的有穷状态机。
1.3 python核心-interpreter解释器/虚拟机
1.3.1 scanner
词法分析,将文件输入的python源代码或从命令行输入的一行行python代码分为一个个的token
1.3.2 parser
语法分析,在Scanner的分析结果上进行语法分析,简历抽象语法树(AST)
1.3.3 compiler
编译字节码,根据AST生成指令集合——python字节码(byte code)
1.3.4 Code Evaluator
虚拟机,执行字节码。
二、Python源代码的组织
下载源码地址:https://www.python.org/downloads/release/python-372/
2.1 Include
该目录下包含了Python提供的所有头文件,如果用户需要用C/C++来编写自定义模块扩展Python,那么久需要用到这里提供的头文件。
2.2 Lib
包含了Python自带的所有标准库,Lib中的库都是Python语言编写的。
2.3 Modules
包含了所有用C语言编写的模块,比如random,cStringIO等。Modules中的模块是那些对速度要求非常严格的模块,而有一些对速度没有太严格要求的模块,用Python编写,放在Lib下。
2.4 Parser
包含了Python解释器中的Scanner和Parser部分,即对Python源代码进行词法分析和语法分析部分。
2.5 Objects
包含了所有Python的内建对象,包括整数、list、dict等。同时,该目录还包括了Python在运行时需要的所有的内部使用对象的实现。
2.6 Python
包含了Python解释器中的Compiler和执行引擎部分,是python运行的核心所在。
2.7 PCBuild
包含了Visual Studio的工程文件,研究Python源代码就从这里开始。
三、Unix/Linux 环境下编译Python
3.1 进入解压文件夹
/Users/kenwu/Desktop/pythonsyscode/pythonsource/Python-3.7.2
3.2 添加配置
./configure --prefix=/usr/python372 注意:这里配置 python 的安装目录,自带的 python 一般安装在 /usr/bin/ 目录下。 configure 命令执行完之后,会生成一个 Makefile 文件,这个 Makefile主要是被下一步的 make 命令所使用。打开 Makefile 你就会发现,里边制定了构建的顺序
3.3 编译源码
make
3.4 执行安装
make install
注意:报错:zipimport.ZipImportError: can't decompress data; zlib not available 解决方案参见:http://www.code4fs.xyz/article/39/
安装完之后,执行 python 命令,你会发现默认的 python 命令仍旧是指向旧的版本 2.7.10
sudo ln -s /usr/python372/bin/python3 /usr/bin/python3
bin目录下存放的是可执行文件。
lib目录下存放的是python标准库
/usr/python372/lib/libpython3.7m.a 用c语言对python进行扩展时,需要用到这个静态库。
四、Windows下安装编译python
该学习记录来源于陈儒《Python源码剖析》,所以我们按照书本中的版本来创建,同时为了看看新版3的区别,此处我们选择Cpython2.7与3.7
python版本:
Cpython 2.7 https://github.com/python/cpython/tree/2.7 Cpython 3.7 https://github.com/python/cpython/tree/3.7
vs版本:
2017 https://www.python.org/downloads/release/python-250/
.net framework:
4.6.2 https://dotnet.microsoft.com/download/thank-you/net462
4.1 编译Cpython 2.7
1、打开VS2017打开项目cpython-2.7\PCbuild\pcbuild.sln,会提示升级SDK,确定,这会帮我们自动重定向SDK
2、移除冗余目录
我们只关心 pythoncore 目录下的源码,因此可以在解决方案资源管理器中,把其他目录从管理器中移出,避免对后期搜索结果的影响。
但要保留 python 目录,因为该目录下的 python.c 是程序入口。
也就是说最后只保留 pythoncore 和 python 这两个目录在解决方案资源管理器中即可,后期所有的调试工作都在 pythoncore 目录下进行。
3、编译 点击编译报错,如上图。timemodule.c下的标识符timezone、daylight和tzname未定义,这是升级SDK的缘故。 修改文件: a、首先把 cpython-2.7\Modules\posixmodule.c 下的 _PyVerify_fd 函数内容替换为如下代码:
int _PyVerify_fd(int fd) { if (_get_osfhandle(fd) == INVALID_HANDLE_VALUE) return 0; else return 1; }
b、修改cpython-2.7\Modules\timemodule.c 中 inittimezone 函数中报错的变量 timezone、daylight 和 tzname 分别改为 _timezone、_daylight 和 _tzname
c、点击“本地windows调试器”,编译源码,方案为debug-win32
生成文件目录如下:cpython-2.7\PCbuild
4.2 编译Cpython 3.7
1、打开cpython-3.7\PCbuild\pcbuild.sln
2、在解决方案资源管理器中:右键 “python” -> 重定向项目 -> 选择 Windows SDK 版本为 10.0.17134.0 (或其他 Win10 版本的SDK即可),pythoncore 同样的操作,移除这两项之外的目录。
3、在解决方案资源管理器中:右键 “pythoncore” -> 属性 -> 配置属性 -> C/C++ -> 预处理器 -> 右侧编辑“预处理器定义” -> 添加 “X86”
4、编译点击 “本地windows调试器” 开始编译源码,方案为 Debug-Win32
编译成功后在 cpython-3.7\PCbuild\ 目录下会多出两个目录:obj 和 win32
其中win32 目录中存放着编译好的 python二进制可执行文件
由于我们的编译模式为Debug,所以该文件名为 python_d.exe 而不是python.exe
五、修改Python源代码
比如在int_print中输出一个整数:
```c int_print(PyIntObject v, FILE fp, int flags) / flags -- not used but required by interface / { //add by kenwu PyObject* str = PyString_FromString("I am in func int_print"); PyObject_Print(str, stdout, 0); printf("\n");
long int_val = v->ob_ival; Py_BEGIN_ALLOW_THREADS fprintf(fp, "%ld", int_val); Py_END_ALLOW_THREADS return 0;
} ```