Python的内部:简介

2020-09-17 05:56:39

一位朋友曾对我说:你知道吗,对某些人来说,C语言只是一堆扩展成汇编语言的宏。那是几年前的事了(聪明人:也是在llvm之前,好吗?),但这句话让我印象深刻。Kernighan和Ritchie真的看了一个C程序,看到了汇编代码吗?蒂姆·伯纳斯·李上网和你我有什么不同吗?而且,当基努·里夫斯看着那些时髦的绿色胡言乱语汤时,他到底看到了什么?不,说真的,他在那里到底看到了什么?!嗯,回到节目上来。不管怎样,在Guido van Rossum的1只眼睛里,蟒蛇是什么样子的?

这篇文章标志着关于Python内部的系列文章的开始,我之所以写这篇文章,是因为我相信解释一些东西是理解它的最好方式,我非常希望能够在阅读Python代码的同时能够可视化更多的Python的“时髦的绿色胡言乱语汤”。课程内容主要是CPython,主要是py3k,主要是字节码计算(我不是一个很喜欢编译的人)-但实际上执行Python和类似Python的代码(Unladen Swallow、Jython、Cython等)的所有内容在本系列中都可能会被证明是公平的。为了简洁和理智起见,除非另有说明,否则当我提到Python时,我指的是CPython。除非另有说明,否则我还假设使用类似POSIX的操作系统或Linux(如果重要的话)。如果您想了解Python是如何工作的,您应该阅读本文。如果您想为CPython做贡献,您应该阅读本文。你应该读一下这篇文章,找出我会犯的所有错误,在背后嘲笑我,或者写下嘲讽的评论。我知道这只是你表达感情的特殊方式。

我想我会从Python的源代码或者偶尔从其他很好的材料(文档,特别是这个和那个、某些PyCon讲座、搜索python-dev等)中收集我所写的几乎所有内容。一切都在那里,但我真的希望我的努力将所有这些都放在一个你可以RSS订阅的地方,这会让你的旅程变得更容易。我假设读者了解一些C语言,一些操作系统理论,略低于一些汇编(任何架构),略多于一些Python,并且具有合理的UNIX适应性(即,感觉从源安装一些东西很舒服)。如果你对其中一个(或多个)不是相当熟悉,不要害怕,但我也不能保证一帆风顺。此外,如果您没有可以正常工作的工具链来进行Python开发,也许您会想转到这里,按照第二段(以及以后的段落,视情况而定)中所说的去做。

让我们从一些我假设您已经知道的事情开始,但我认为重要的是,至少对我理解…的主要方式而言是如此。嗯,我所理解的一切。我看着它就像在看一台机器。对于Python来说,这很简单,因为Python依赖于虚拟机来完成它所做的事情(就像许多其他解释语言一样)。请确保您在此上下文中正确理解了“虚拟机”:更像JVM而不是VirtualBox(从技术上讲,它们是相同的,但在现实世界中,我们通常将这两种VM区分开来)。我发现最容易理解的字面意思是“虚拟机”--它是一台由软件构建的机器。你的CPU只是一台复杂的电子机器,它接收所有的输入(机器代码,数据),它有一个状态(寄存器),根据输入和它的状态,它会输出东西(到RAM或总线),对吗?嗯,CPython是一台由软件组件构建的机器,它具有状态并处理指令(不同的实现可能使用相当不同的指令)。此软件机器在托管Python解释器的进程中运行。记住这一点;我喜欢机器的比喻(正如我在这里详细解释的那样)。

也就是说,让我们从鸟瞰开始,了解一下执行此操作时会发生什么:$python-c&39;print(";Hello,world!";)';。Python的二进制代码被执行,几乎所有进程都会执行标准C库初始化,然后Main函数开始执行(参见其源代码./Modules/python.c:main,它很快就会调用./Modules/main.c:py_main)。在一些普通的初始化工作(解析参数、查看环境变量是否应该影响行为、评估标准流的情况并采取相应操作等)之后,./python/pythonrun.c:py_Initialize被调用。在很多方面,这个函数就是“构建”和组装运行CPython机器所需的组件,并将“一个进程”变成“一个带有Python解释器的进程”。其中,它创建了两个非常重要的Python数据结构:解释器状态和线程状态。它还创建内置模块sys和托管所有内置模块的模块。在稍后的帖子中,我们将深入讨论所有这些内容。

准备就绪后,Python将根据其执行方式执行以下几项操作中的一项。粗略地说,它要么执行字符串(-c选项),要么将模块作为可执行文件执行(-m选项),或者执行文件(pass

PyEval_EvalFrameEx获取帧,在操作码之后提取操作码(以及操作数,如果有操作数,我们将了解到这一点),并执行与操作码匹配的一小段C代码。让我们通过反汇编一些已编译的Python代码来更仔细地了解这些“操作码”是什么样子:

…。即使不太了解Python的字节码,这也是相当可读的。您“加载”了名称“鸡蛋”(您从哪里加载它?你把它装到哪里?不久),并且还加载一个常量值(1),然后执行“二进制减法”(在此上下文中“二进制”是什么意思?在哪些操作数之间?),以此类推。正如您可能已经猜到的那样,名称是从我们前面看到的全局和局部名称空间“加载”的,并且它们被加载到一个操作数堆栈(不要与正在运行的帧的堆栈混淆),这正是二进制减法将从其中弹出它们的位置,从另一个中减去一个,然后将结果放回那个堆栈中。“二进制减法”只是表示这是一个具有两个操作数的减法操作码(因此它是“二进制”的,这并不是说操作数是由“0”和“1”组成的二进制数)。

您可以自己查看PyEval_EvalFrameEx at./python/ceval.c,它无论如何都不是一个小函数。出于实际原因,我不能在这里粘贴太多代码,但我将只粘贴在找到BINARY_SUBTRACT操作码时运行的代码,我认为它确实说明了问题:

…。弹出一些东西,取(操作数堆栈的)顶部,对这些事情调用一个名为PyNumber_Subtract()的C函数,在这两个操作上做一些我们仍然不理解(但会在适当的时候)称为“Py_DECREF”的操作,将堆栈的顶部设置为减法的结果(覆盖以前的顶部),然后做一些我们不理解的事情(如果x不为NULL),即执行“分派”。因此,虽然我们有一些不理解的东西,但我认为在Python中如何在尽可能低的级别上将两个数字相减是非常明显的。我们也只用了1500个字就到了这里!

在执行框架并返回PyRun_SimpleStringFlags之后,Main函数进行一些清理(特别是Py_Finalize,我们将讨论这一点),完成标准C库反初始化工作(atexit等),然后进程退出。

我希望这能给我们一个“足够好”的概述,稍后我们可以将其作为脚手架,在后面的帖子中,我们将对Python的各个领域进行更具体的讨论。我们承诺要回到相当多的术语上:解释器和线程状态、名称空间、模块和内置、代码和框架对象,以及那些我们在BINARY_SUBTRACT的实现中不理解的DECREF和分派行。还有一个非常重要的“幻影”术语,我们在本文中一直在讨论,但没有使用名称-对象。CPython的对象系统是理解其工作原理的核心,我认为我们将在本系列的下一篇文章中详细介绍这一点。敬请关注。

1请注意,除非明确说明,否则本系列不支持或附属于任何人。另外,请注意,虽然Python是由Guido van Rossum发起的,但多年来很多人为它和衍生项目做出了贡献。我从来没有问过Guido,也没有问过他们,但我确信Python对这些贡献者中的许多人来说并不比Guido看得更清楚。

很棒的帖子-写得很好,主题很吸引人。关于Python内部结构的系列承诺让我立即将您的博客添加到我的RSS阅读器中:-)

我还写了一些关于Python的内部结构(http://eli.thegreenplace.net/2009/11/28/python-internals-working-with-python-asts/))的文章,并计划写更多-重点放在编译方面,这是我非常喜欢的,所以我们的材料可能会成为补充。

对于Tim在Web上的观点来说,好消息是,它可以在Web上访问。:)蒂姆在很长一段时间里一直在写一本关于Web架构和哲学的日记。

非常酷的东西,是的,相当多的人应该从这类文章中学到一些东西。

很棒的帖子,但是因为这个系列的RET会一样长,请停止使用低对比度的灰色字体。

与我相比,您包含了更多特定于实现的细节(这显然是重点的一部分),但我认为许多核心概念将是共同的(也是重要的)。

[…]。安德鲁·格里夫,弗兰克·沃斯利和本·莫兰,克里斯托夫·拉兰在推特上提到了这篇帖子。Christophe Lalanne说:rt@benm:这是Yaniv Aknin关于PythonKindle内部的一系列很好的博客,如http://bit.ly/hmEJvy的电子书:http://b…。[…]。

[…]。在口译员级别工作,请通读整个Python Innards&34;Series https://tech.blog.aknin.name/2010…。Embedded QuoteComment正在加载…。·分享·嵌入·刚刚,安库尔·古普塔,[…]。

[…]。在口译员级别工作,请通读整个Python Innards&34;Series https://tech.blog.aknin.name/2010…。Embedded QuoteComment正在加载…。·分享·嵌入·9小时前,安库尔·古普塔,[…]

[…]。一些能让她入睡的东西。因为她不是一个真正的黑客,我想一些关于我通常写的东西的讨论可能会起到作用(好的,也许“不完全是一个黑客”是轻描淡写的,她是一个[…])