CPython Internals
参考 https://realpython.com/cpython-internals/resources/, 此书基于 cpython3.9.0b1
Compiling Cpython
使用 python 源码编译的步骤如下:
git clone -b v3.9.0b1 --depth=1 https://github.com/python/cpython.git
sudo apt install build-essential
sudo apt install libssl-dev zlib1g-dev libncurses5-dev libncursesw5-dev libreadline-dev libsqlite3-dev libgdbm-dev libdb5.3-dev libbz2-dev libexpat1-dev liblzma-dev libffi-dev
cd cpython
# configure 是一个可执行 shell 脚本, 它是由 autoconf 工具(命令)生成的, 其更原始的文件可能是代码库中的 configure.ac 这种文件通过 autoconf 命令得到的, 但是通过其他文件得到 configure 脚本的过程似乎是由 Python 开发者手工执行 autoconf 命令后上传至代码仓库并且被 git 所管理的, 因此 configure 脚本本身是怎么得到的这一细节暂时不太清楚
# ./configure 的执行结果主要是得到 Makefile 文件(以及一些其他文件, 具体有哪些不太确定, 按理是 make 命令执行时所需的配置文件), 注意这个 Makefile 文件并不由 git 所管理
# 目前的一些观察: git 会管理 configure 和 Makefile.pre 文件, 而后者似乎是最终生成的 Makefile 的模板, 猜测在执行 ./configure 脚本时, 应该是使用到了 Makefile.pre 文件的
# 总之: 就目前来说, ./configure 命令只需要执行一次, 后续即使改动了 Cpython 源代码, 需要重新编译时, 也只需要执行 make 命令, 而不需要执行 ./configure 命令. 因此研究和探索 Cpython 的起点可以定在 Makefile 已经得到了.
./configure --with-pydebug
# 使用下面的命令得到的二进制文件 python 只会在当前路径下, 不会被复制进 /bin, /usr/bin, /usr/local/bin 这类路径, 因此不用担心对全局的 python 有任何污染
make -j2 -s
# make install 会将编译好的 python 复制进 /bin, /usr/bin, /usr/local/bin 这类路径, 并且会修改 python 命令的指向, 例如: 首先将编译好的 python 复制进 /usr/bin/python3.9, 然后构建 /usr/bin/python -> /usr/bin/python3.9 这种软链接, 因此不推荐这种做法, 而是推荐用 make altinstall
# make install
# make altinstall 不会修改 python 命令的软链接, 因此是推荐的安装方式
# make altinstall
# 注意: 我们不想对全局的 python 或 python3 或 python3.x 有任何污染, 因此我们既不执行
# 使用如下方式运行编译好的 python
./python使用 configure 脚本得到的 Makefile 很冗长, 暂时没法过于细究, 但这确实是一切事情的“主入口”, 因此很有必要知道 make -j2 -s 具体执行了什么. 对这里用到的 make 命令做些简单介绍, -j2 是打开多线程编译 (大约就是各个 .c 文件编译为 .o 文件是没有先后依赖的, 所以可以通过多线程来加速编译过程), -s 的作用只是不打印具体的执行命令, 但出于学习考虑, 知道 make 的具体执行内容是重要的, 而直接读 Makefile, 里面的分支过于繁杂, 这种时候, 可以使用 make -n 命令来得知 make 的具体执行步骤, 注意: make -n 只打印需要执行的命令, 但它不会真的执行:
输出内容大体如下:
总之, make 命令的最终目的主要就是得到 python 可执行文件, 到此为止, 我们需要明确目标: 在执行 python xx.py 时到底发生了什么, 这里先简单探索下: 首先, 我们知道 ./Programs/python.c 文件里应该有作为入口的 main 函数, 然后 xx.py 作为命令行参数传递给了这个 main 函数, 我们简单看一下 ./Programs/python.c 的文件内容, 果然不出所料, 包含下面的代码
所以这里便是一切的主入口了, 值得注意的是 Cpython 的实现语言是 C 语言, 而非 C++ 语言.
如果没有任何参考资料, 只能“顺藤摸瓜”学习源代码的话, 下一步便是继续深入 main 函数, 了解它每一步都在做啥. 参考书介绍了各种组件, 因此最后还缺乏一个从 main 入手的总览, TODO: 这个步骤非常重要, 但留待后续研究清楚后再补齐.
The Python Language and Grammar (TODO)
本章主要是介绍 Python 的语法, 所谓语法就是: 文本文件符合什么书写规范时, 才能被执行. 从“微观层面”说: 譬如说 python 语言中规定的 if 语句得这么写:
而不能是 C 语言的写法:
我们可以想象, 应该会有一个文件规定了 python 语言的语法, 并且 python 可执行程序(也就是 python 解释器) 也是根据这个文件来将 xx.py 文件转化为具体的执行指令的. 这个文件也就是语法文件.
Configuration and Input
Last updated
Was this helpful?