大师兄的Python源码学习笔记(一): 准备工作
2021-01-27 本文已影响0人
superkmi
一、总体架构
- 在最高层次上,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下配置源码编译环境
- 1) 点击下载源码
- 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