社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

Python 3.8 已发布,那如何编译和调试最新的内核源码呢?

Python猫 • 4 年前 • 367 次点击  

👆 Python猫” ,一个值得加星标的公众号

花下猫语:Python 的大版本 3.8 已发布。之前,我们分享过《Python 3.8 带来了哪些新鲜功能?》、《英文 | 快来尝鲜Python 3.8 的赋值表达式》,预告过这次更新。借着这个话题,今天分享一篇文章,介绍如何调试最新的 Python 内核源码。祝阅读愉快!


作者:shine-lee(本文经作者授权转载)
来源:https://www.cnblogs.com/shine-lee/p/11685775.html

剧照 | 《浓情巧克力》

写在前面

如果对 Python 源码感兴趣,那“窥探”其实现的最佳方式就是调教它,不,调试它。

获取源代码

Python 的官方默认实现为 CPython,即 C 语言实现(主要指解释器的实现,其他实现见 Other Interpreter Implementations)。CPython 的源代码可以从官网 pyhton.org 或者 github.com/python/cpython 获取,目前最新的稳定版本为 3.8.0,于 2019.10.14 发布。

这里,从官网 https://www.python.org/downloads/release/python-380/ 下载源码压缩包,如下图所示:

源代码的组织

解压后,目录结构如下




    
{ Python-3.8.0 }  » tree -d -L 1 .
.
├── Doc         # rst(reStructuredText)格式官方文档,用其生成https://docs.python.org/
├── Grammar     # Python的EBNF(Extended Backus–Naur form)语法定义文件
├── Include     # .h 头文件
├── Lib         # .py 纯Python实现的标准库
├── m4          # ?
├── Mac         # Mac-specific code,支持MacOS
├── Misc        # Things that do not belong elsewhere.
├── Modules     # C实现的标准库,内含.c .asm .macros .h
├── Objects     # 内置数据类型实现
├── Parser      # Python语法分析器源码
├── PC          # Windows-specific code,支持Windows
├── PCbuild     # Windows生成文件,for MSVC
├── Programs    # main函数文件,用于生成可执行文件,如python.exe的入口文件
├── Python      # CPython解释器源码
└── Tools       # 独立工具代码,used to maintain Python

CPython 的源码组织结构如下,摘抄自 CPython Source Code Layout:

源码文件分门别类存放,而且,无论是 py实现的标准库、c实现的标准库、内置数据类型还是内置函数,在Lib/test/Doc/library/目录下都有与之对应的 test_x.py 测试文件和 rst 文档文件(对于内置数据类型和函数,其文档集中保存在 stdtypes.rst 和 functions.rst)。比如,内置类型int位于Objects/longobject.c文件中。

下面正式开始编译 CPython。

windows下编译CPython

据 Compile and build on Windows,Python3.6 及之后的版本可以使用 VS2017 编译,安装 VS2017 时,记得勾选 Python developmentPython native development tools,有备无患。

安装好 VS2017 后,双击PCbuild/pcbuild.sln,打开解决方案。因为我们的关注点仅在 Python 内核和解释器部分,所以仅编译 python和pythoncore,其他模块暂时忽略,具体地,
  • 切换到debug win32

  • 右键解决方案→属性→配置属性

  • 仅勾选项目python和pythoncore

  • 确定

此时再“生成解决方案”,生成目录为PCbuild/win32,内容如下,含解释器 python_d.exe 和内核 python38_d.dll

接下来,将项目 python 设为启动项目(默认状态即是启动项目),点击调试,运行得到如下控制台,可以像平时使用 python 一样,与之交互。

如果想生成全部模块,需要运行PCbuild\get_externals.bat下载依赖,再编译,具体可参见 Build CPython on Windows。

调试CPython

只要程序能运行起来,一切就好办了。凭借“宇宙最强IDE”,我们可以任性地设断点调试甚至修改代码。

F5重新启动调试,弹出控制台。在上面我们知道int类型位于Objects/longobject.c文件,打开文件,简单浏览后在函数PyObject * PyLong_FromLong(long ival)入口处打个断点。

然后,在弹出的控制台中输入a = 1来创建int对象,回车,程序停在了断点处,查看变量ival的值为 1——恰为我们输入的数值,这个函数会跟根据输入的 C long int 创建一个 int 对象,返回对象指针

再来看看函数调用堆栈,如下图所示:

调用顺序从下至上,从中可以推断出:
  • 从python_d.exe的入口main运行起来后,进入python38_d.dll

  • 从标准输入stdin中读取键入的字符串

  • 解析字符串,建立了语法树AST(abstract syntax tree)

  • 解析语法树中的节点,判断字符为number,将字符串转化为C long int

  • 由C long int创建Python的int对象

继续运行,弹出的控制台中光标前出现<<<,等待输入。这时如果我们点击调试中的停止按钮(全部中断),会发现程序停在Parser/myreadline.c文件_PyOS_WindowsConsoleReadline函数中的ReadConsoleW一行,

if (!ReadConsoleW(hStdIn, &wbuf[total_read], wbuflen - total_read, &n_read, NULL)) {
    err = GetLastError();
    goto exit;
}

ReadConsoleW为 WINAPI,详见 ReadConsole function,其等待并读取控制台的输入,读取的字符保存在wbuf中。如果有输入,则进入上面的流程,解析→建立语法树→……

小结

至此,我们揭开了 Python 面纱的一角——不过是一个可运行、可调试的程序而已(微笑)。

参考

  • Directory structure

  • reStructuredText

  • Extended Backus–Naur form

  • Exploring CPython’s Internals

  • Compile and build on Windows

优质文章,推荐阅读:

GIL 已经被杀死了么?

Python工匠:解析容器类型的门道

Python 之父退位后,最高决策权花落谁家?

Python 是用 C 语言实现的,那 C 是用什么语言实现的?

感谢创作者的好文
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/47231
 
367 次点击