一、总体架构

在最高层次上,Python可以分为三个主要部分:文件组(File Group)、核心(Python Core)和运行环境(Runtime Environment)

1. 文件组(File Groups)

文件组包含以下三部分:

核心模块(Core modules): Python自带的内建模块。

库(Library): 第三方包。

用户自定义模块(User-defined Modules):用户自定义扩展的模块。

2. 核心(Python Core)

包含Python的解释器(interpreter)。

在解释器中,箭头方向指示了Python运行过程中的数据流方向:

1) Scanner对应词法分析,将Python源码分为一个个token。

2) Parser在Scanner的分析结果上进行语法分析,建立抽象语法树(AST)。

3) Complier根据AST生成指令集合-Python字节码(byte code)。

4) Code Evaluator执行字节码,也可以称为虚拟机。

3. 运行环境(Runtime Environment)

运行环境包含一下三个部分:

1) 对象/类型系统(Object/Type structures):包含了各种内建对象,比如int、list、dict和各种用户自定义的类型和对象。

2) 内存分配器(Memory Allocator):负责创建对象时的内存申请。

3) 运行时状态信息(Current State Of Python):维护解释器再执行字节码时不同的状态之间切换的动作。

解释器与对象/类型系统和内存分配器之间的箭头表示使用关系。

解释器与运行时状态之间的箭头表示修改关系。

二、Win10下配置源码编译环境

2) 解压tar文件后进入到PCbuild目录。

3) 用vscode2019打开PCbuild/pcbuild.sln文件,升级SDK。

4) 在左侧目录顶端右键点击属性

5) 选择生成配置

6) 生成解决方案

7) 在PCbuild/win32文件夹中生成了解释器python_d.exe

三、源代码组织

.
├── Doc
├── Grammar
├── Include
├── LICENSE
├── Lib
├── Mac
├── Makefile.pre.in
├── Misc
├── Modules
├── Objects
├── PC
├── PCbuild
├── Parser
├── Programs
├── Python
├── README.rst
├── Tools
├── aclocal.m4
├── config.guess
├── config.sub
├── configure
├── configure.ac
├── install-sh
├── m4
├── pyconfig.h.in
└── setup.py

Doc目录:主要是官方文档的说明。

include目录:包含了所有头文件,如果用户需要用C或C++编写自定义模块扩展Python,就需要用到头文件。

lib目录:包含了Python自带的所有标准库,lib中的库是用Python编写的。

Objects目录:包括了内建对象。

Parser目录:包括了python编译相关代码,将python文件编译生成语法树等相关工作。

Programs目录主要包括了python的入口函数。

Modules 目录:包含了所有用 C 语言编写的模块,比如 math、hashlib 等。它们都是那些对速度要求非常严格的模块。而相比而言,Lib 目录下则是存放一些对速度没有太严格要求的模块,比如 os。

Python目录:主要包括了Python动态运行时执行的代码,里面包括编译、字节码解释器等工作。

四、修改源码

如果在研究源码的过程中,如果需要输出中间结果,则就需要借助 Python C API 中打印对象的接口。

比如希望在处理int时增加一段字符串输出,将object/longobject.c文件中的以下函数:

static PyObject *
long_to_decimal_string(PyObject *aa)
{
PyObject *v;
if (long_to_decimal_string_internal(aa, &v, NULL, NULL, NULL) == -1)
return NULL;
return v;
}
修改为:
static PyObject *
long_to_decimal_string(PyObject *aa)
{
PyObject *str = PyUnicode_FromString("here before int");
PyObject_Print(str, stdout, 0);
printf("\n");
PyObject *v;
if (long_to_decimal_string_internal(aa, &v, NULL, NULL, NULL) == -1)
return NULL;
return v;
}
重新生成编译器后生效:
Python 3.7.2 (default, Jan 27 2021, 11:30:56) [MSC v.1925 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> print(1)
'Here before int'
1