4

为什么 Cpython 是 C 写的,而不是 Python

 2 years ago
source link: https://www.techug.com/post/why-is-cpython-written-in-c-not-python.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.


img16435704071506580745.jpeg

CPython 中的 C 是指 C 语言,意味着这个 Python 默认发行版是用 C 语言编写的。其实,CPython 的编译器是用纯 C 语言编写的,或者是 C 和 Python 的组合。那我们不经要问:

为什么 Cpython 不是用其他语言

我们首先要知道,高级语言都要编译为机器语言。所以区别就在于编译器的工作方式中,有两种类型的编译器:

  1. 自我实现编译器:如 Go 语言,一开始也是 C 语言实现的编译器,后面逐渐使用 Go 重写编译器;

  2. 源到源编译器:是用另一种已经有编译器的语言编写的编译器。开发新语言时用已经完善且成熟的编译器编写,节省时间和学习成本。

Python 解释器中默认和最流行实现是 CPython 。使用它有一个重要的优势。C 是编译语言,其代码转换为机器代码,由中央处理单元(CPU)直接执行。

为什么 Python 最常见的解释器是 C 语言编写的,那为什么不是 Python 或者 C++ 等编程语言呢?

这是一种实用和历史原因的组合。(主要是)历史原因是 CPython 1.0 于 1989 年发布。当时,C 最近是标准化的。C ++几乎是未知的并且明确不可移植,因为几乎没有人有 C ++编译器。

Linux 之父 —— Linus Torvalds 无敌不喜欢 C ++,并且多次向 C++ 表示抗议。

Python 之父 Guido 也没有表示对 C ++ 的那种强烈的负面情绪。

尽管 C++ 在今天更广泛且更容易获得,但将 CPython 重写为与 C++ 兼容的 C 仍需要大量工作。就其本身而言,这项工作几乎没有或根本没有真正的好处。

并非百分百的 C

C(CPython)中的 Python 实现不是 100% 编译的,也不是 100% 解释的。在运行 Python 脚本的过程中,既有编译也有解释。为了清楚起见,让我们看看运行 Python 脚本的步骤:

  • 使用 CPython 编译源代码生成字节码

  • 在 CPython 解释器中解释字节码

  • 在 CPython 虚拟机中运行 CPython 解释器的输出

当 CPython 编译源代码(.py 文件)来生成 CPython 字节码(.pyc 文件)时,会进行编译。然后使用 CPython 解释器解释 CPython 字节码(.pyC 文件),输出在 CPython 虚拟机中运行。根据上述步骤,运行 Python 脚本的过程同时涉及编译和解释。

CPython 编译器仅生成一次字节码,但每次代码运行时都会调用解释器。通常对字节码的解释需要很多时间。如果使用解释器慢下来,为什么要使用它?大的原因是它有助于使 Python 跨平台。由于字节码在 CPU 的顶部的 CPython 虚拟机中运行,因此它独立于它运行的机器。因此,字节码可以不变地运行不同的机器。

CPython 保持其 C 的传统:许多标准库模块,如 ssl 模块或 sockets 模块,都是用 C 写好的,用以访问底层操作系统 API。Windows 和 Linux 内核中用于创建网络 sockets 的 API、使用文件系统和与显示交互的都用 C 编写。

Python 专注于 对 C 语言层面上的扩展。

如果没有使用解释器,那么 CPython 编译器将生成直接在 CPU 中运行的机器代码。因为不同平台有不同的指令,所以代码不会跨平台。

总之,使用编译器加快过程,但解释器使代码跨平台。因此,Python 比 C 慢的原因是使用解释器。请记住,编译器刚刚运行一次,但每次执行代码时都会运行解释器。

Python 比 C 慢得多,但许多程序员仍然更喜欢它,因为它更容易使用。Python 从程序员隐藏了许多细节,这可以帮助防止令人沮丧的调试。例如,由于 Python 是一种动态键入的语言,您不必明确指定代码中的每个变量的类型 – Python 将自动推断出来。相比之下,具有静态类型语言(如 C,C ++ 或 Java),您必须指定变量的类型,如下所示。

int x = 2022
string s = "Hello, World"

将此与以下 Python 中的实现进行比较。动态类型使编码更容易,但增加了机器寻找合适数据类型的负担。这会使过程变慢。

x = 2022
s = "Hello, World"

一般来说,像 Python 这样的“更高级别”语言更容易用于开发人员。但是,当运行代码时,需要将其转换为低级指令。简单易用的这种转换带来的牺牲是需要更多的时间。

如果时间是一个重要因素,那么您需要使用较低级别的指令。比如直接使用 C 语言、C++ 或者时兴的 Rust。

当然,如今,CPython 不再是唯一的 Python 实现。还有如下的 Python 解释器:

  • Stackless Python(支持微线程的 CPython 分支)

  • IronPython(在 .NET 上运行的 Python)

  • Jython(在 Java 虚拟机上运行的 Python)

  • PyPy(带有 JIT 编译器的快速 python 实现)

  • RPython(Python 的静态类型子集)编写的 PyPy

  • NQP 和 PIR 中的 Pynie 等等

总结就是众多的历史原因让吉多大叔选择了用 C 语言写出 Python 的解释器,而 Python 的设计原则为了追求简洁的语法牺牲了一定的时间,所以官方默认的解释起依旧是 CPython。

而为了开发者的方便,时至今日,还有更多其他的解释器版本,而不是弃用原有的 CPython 的底层 API ,选择用 Python 自我实现的解决方案。

好了,这就是为什么 CPython 不用其他语言实现的原因了,希望您看到这里能有帮助。

下一篇文章见!

灵感来源:https://realpython.com/cpython-source-code-guide/

本文文字及图片出自 InfoQ


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK