Python源码学习笔记-0

发布在 编程

Python

0. 前言

年初的时候给自己挖了一个坑,计划要在今年过一遍Python的源码。结果这一年零零碎碎总有事情耽搁了。现在已经10月份了,再不填坑就来不及了。于是有了这个系列。

说到看Python源码,陈儒的Python源码剖析可谓经典了。本系列基本也是根据此书的结构的。不过此书出版已近十年(2016-10),Python版本也从2.5到了3.5。不才能力有限,姑妄言之。

运行环境:Bash on Ubuntu on Windows,同样适用其他于UNIX-like环境。

1. 获取Python源码

你可以选择2.7.123.5.2。当然你也可以使用hg clone https://hg.python.org/cpythonhg update 3.5这样的命令来选择你喜欢的版本分支。(hg通过sudo apt install mercurial安装)

值得注意的是,CPython会检测到是否是从工作拷贝(由hg clone的)运行。这意味着如果你在你的拷贝中编辑CPython源码,Python代码(.py文件)的改变会被解释器立即使用和测试。(如果你修改的是C代码,你将需要重新编译受影响的文件)。

2. 编译为调试模式

CPython提供几种编译flag帮助调试很多东西。所有已知的flag都可以在Misc/SpecialBuilds.txt文件中找到,最常用的是Py_DEBUG标志。

暂时还不清楚SpecialBuilds中的编译选项的具体用法,搞明白之后再更新。

构建debug版的Python,可以在源码根目录中运行./configure --with-debug

Python源码剖析中有提到--enable-shared,如果你不知道是干什么的建议不要加上,不然会链接到系统自带的Python的。

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

注释和共享

  • 第 1 页 共 1 页
作者的图片

唐梓涯

Pythoner, Emacser, GNU/Linuxer
目前在微软技术支持掏粪


全栈工程师


中国无锡