Python源码学习笔记-0
0. 前言
年初的时候给自己挖了一个坑,计划要在今年过一遍Python的源码。结果这一年零零碎碎总有事情耽搁了。现在已经10月份了,再不填坑就来不及了。于是有了这个系列。
说到看Python源码,陈儒的Python源码剖析可谓经典了。本系列基本也是根据此书的结构的。不过此书出版已近十年(2016-10),Python版本也从2.5到了3.5。不才能力有限,姑妄言之。
运行环境:Bash on Ubuntu on Windows,同样适用其他于UNIX-like环境。
1. 获取Python源码
你可以选择2.7.12或 3.5.2。当然你也可以使用hg clone https://hg.python.org/cpython
和hg update 3.5
这样的命令来选择你喜欢的版本分支。(hg通过sudo apt install mercurial安装)
值得注意的是,CPython会检测到是否是从工作拷贝(由hg clone的)运行。这意味着如果你在你的拷贝中编辑CPython源码,Python代码(.py文件)的改变会被解释器立即使用和测试。(如果你修改的是C代码,你将需要重新编译受影响的文件)。
2. 编译为调试模式
CPython提供几种编译flag帮助调试很多东西。所有已知的flag都可以在Misc/SpecialBuilds.txt
文件中找到,最常用的是Py_DEBUG
标志。
构建debug版的Python,可以在源码根目录中运行./configure --with-debug
2.1. 构建依赖
CPython的核心解释器需要C编译器构建。一些拓展模块也依赖额外的库。
Debian/Ubuntu系的可执行如下命令安装依赖:
sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils
Mac OS X:
brew install readline xz
其他发行版本参见参考资料[2]。
3. 目录结构
大部分的子文件夹都有自己的README。大部分的文件都有注释。
文件或文件夹 | 简介 |
---|---|
Demo/ | 示例脚本,模块和程序 |
Doc/ | 文档源(reStructuredText) |
Grammar/ | Python的EBNF语法文件 |
Include/ | 公共头文件 |
LICENSE | 授权信息 |
Lib/ | Python部分标准库,均是Python写的 |
Mac/ | Macintosh特定的资源(例如,用IDLE作为OS X的应用) |
Makefile.pre.in | Source from which config.status creates the Makefile.pre |
Misc/ | 其他有用的文件 |
Modules/ | 大部分内置模块的实现 |
Objects/ | 大部分内置对象类型的实现 |
PC/ | PC特定的文件(DOS, Windows, OS/2) |
PCbuild/ | Microsoft Visual C++的build目录 |
Parser/ | 解析器和分词器以及他们的输入处理AST的节点也在这个文件夹 |
Python/ | 字节编译器和解释器,Python核心部分。 |
README | 读我 |
RISCOS/ | RISC操作系统特定的文件 |
Tools/ | 一些用Python写的有用的程序 |
pyconfig.h.in | Source from which pyconfig.h is created (GNU autoheader output) |
configure | 配置的shell脚本(GNU autoconf的输出) |
configure.ac | 配置格式(GNU autoconf的输入) |
install-sh | 用来安装文件的Shell脚本 |
4. 贴士
4.1. Py_ssize_t
首先理解什么是size_t,然后是ssize_t,然后你就知道什么是Py_ssize_t了。
4.2. int_repr
在最新的Python代码中没有了int_repr这个函数,甚至没有了intobject。善用搜索引擎,发现了旧版本的intobject.c中有两处int_repr,一处是定义,一处是引用。(reprfunc)int_repr, /* tp_repr */
拿注释tp_repr
在新版里搜,发现了long_to_decimal_string, /* tp_repr */
不出意外这就是改动后的函数,试试再按Python源码剖析的例子操作,成功输出。
参考资料:
[1] Python Developer’s Guide — Python Developer’s Guide
[2] Common build problems · yyuu/pyenv Wiki