0

我一直在编译图表(双关语),希望了解常见编程语言的不同实现。我了解代码是编译还是解释取决于代码的实现,而不是编程语言本身的一个方面。

我有兴趣将 Python 解释与直接编译(前 C++)进行比较

在此处输入图像描述

和虚拟机模型(例如 Java 或 C#)

在此处输入图像描述

根据上面的这两个图,请你帮我开发一个类似的流程图,说明如何将 .py 文件转换为 .pyc,使用标准库(我认为它们称为模块)然后实际运行。SO 上的许多程序员表示,作为脚本语言的 python 不是由 CPU 执行,而是由解释器执行,但这听起来很不可能,因为最终必须由硬件进行计算。

4

3 回答 3

3

首先,这是一个实现细节。我将我的答案限制在 CPython 和 PyPy 上,因为我熟悉它们。Jython、IronPython 和其他实现的答案会有所不同——可能根本不同。

Python 更接近于“虚拟机模型”。Python 代码,与一些对他们的知识水平来说太大声的人的陈述相反,尽管每个人(包括我)在随意的讨论中都将它混为一谈,但从未被解释过。它在加载时总是被编译成字节码(同样,在 CPython 和 PyPy 上)。如果它是因为模块被导入并从 .py 文件加载而被加载的,则可能会创建一个 .pyc 文件来缓存编译输出。此步骤不是强制性的;您可以通过各种方式将其关闭,并且程序执行不会受到任何影响(除非下一个加载模块的过程必须再次执行)。但是,编译成字节码是不可避免的,如果不是从磁盘加载,字节码是在内存中生成的。

然后在模块级别执行此字节码(其确切细节是实现细节并且版本之间不同),这需要构建函数对象、类对象等。这些对象只是重用(持有指向)已经在内存中的字节码。这与 C++ 和 Java 不同,其中代码和类在编译期间/之后是一成不变的。在执行过程中,import可能会遇到语句。我缺乏篇幅、时间和理解来描述进口机械,但简短的故事是:

  • 如果它已经被导入一次,您将获得该模块对象(静态语言仅在编译时具有的另一个运行时构造)。在任何 Python 代码运行之前,已经导入了几个内置模块(好吧,它们都在 PyPy 中,原因超出了这个问题的范围),这仅仅是因为它们与解释器的核心紧密集成并且非常基础。sys就是这样一个模块。一些 Python 代码也可以预先运行,尤其是当您启动交互式解释器时(查找site.py)。
  • 否则,模块被定位。这方面的规则不是我们关心的。最后,这些规则到达 Python 文件或动态链接的机器代码片段(Windows 上的 .DLL,虽然 Python 模块专门使用扩展名 .pyd 但这只是一个名称;在 unix 上使用等效的 .so )。
    • 模块首先加载到内存中(动态加载,或解析并编译为字节码)。
    • 然后,模块被初始化。扩展模块对被调用的对象有一个特殊的功能。Python 模块只是从上到下运行。在表现良好的模块中,这只是设置全局数据、定义函数和类以及导入依赖项。当然,其他任何事情也可能发生。生成的模块对象被缓存(记住第一步)并返回。

所有这些都适用于标准库模块以及第三方模块。这也是为什么如果您调用您的脚本就像您在该脚本中导入的标准库模块一样调用您的脚本(它会自行导入,尽管不会由于缓存而崩溃 - 这是我忽略的许多事情之一),您可能会收到一条令人困惑的错误消息。

字节码的执行方式(问题的最后一部分)不同。CPython 只是简单地解释它,但正如您正确指出的那样,这并不意味着它神奇地不使用 CPU。取而代之的是一个大而丑陋的循环,它检测接下来应该执行什么字节码指令,然后跳转到一些执行该指令语义的本机代码。PyPy 更有趣;它开始解释但沿途记录一些统计数据。当它认为值得这样做时,它开始详细记录解释器所做的事情,并生成一些高度优化的本机代码。解释器仍然用于 Python 代码的其他部分。请注意,它与许多 JVM 和可能的 .NET 相同,但您引用的图表掩盖了这一点。

于 2012-06-29T19:42:18.553 回答
1

对于python的参考实现:

(.py) -> python (检查 .pyc) -> (.pyc) -> python (执行动态加载模块)

还有其他实现。最值得注意的是:

  • jython将 (.py) 编译为 (.class) 并从那里遵循 java 模式
  • pypy在编译时使用JIT (.py)。那里的链可能会有所不同(pypy 可以在 cpython、jython 或 .net 环境中运行)
于 2012-06-29T18:58:57.513 回答
0

Python 从技术上讲是一种脚本语言,但它也是经过编译的,python 源代码从其源文件中获取并输入解释器,解释器通常在内部将源代码编译为字节码,然后将其丢弃或在外部将其像 .pyc 一样保存

是的,python 是单个虚拟机,然后位于实际硬件之上,但所有 python 字节码都是 pvm(python 虚拟机)的一系列指令,就像实际 CPU 的汇编程序一样。

于 2012-06-29T18:58:31.663 回答