CPython 是如何实现的?

How is CPython implemented?

所以我最近看到了对 Python 的解释器和编译器(特别是 CPython)的解释。

如有错误请指正。我只是想确定我理解这些具体概念。

所以 CPython 既被编译(到字节码)又被解释(在 PVM 中)? PVM 究竟做了什么?它是否逐行读取字节码,并将每一个字节码翻译成可以在特定计算机上执行的二进制指令? 这是否意味着基于 Intel 处理器的计算机需要与基于 AMD 的计算机不同的 PVM?

  1. 是的,CPython被编译为字节码,然后由虚拟机执行。
  2. 虚拟机执行指令one-by-one。它是用 C 编写的(但你可以用另一种语言编写)并且看起来像一个巨大的 if/else 语句,如“如果当前指令是这样,则执行此操作;如果指令是此,则执行其他操作”,等等在。指令没有被翻译成二进制——这就是为什么它被称为 解释器 的原因。
    1. 您可以在此处找到说明列表:https://docs.python.org/3.10/library/dis.html#python-bytecode-instructions
    2. VM 的实现可在此处获得:https://github.com/python/cpython/blob/f71a69aa9209cf67cc1060051b147d6afa379bba/Python/ceval.c#L1718
  3. 字节码没有“行”的概念:它只是一个字节流。解释器可以一次读取一个字节并使用另一个 if/else 语句来决定它正在查看的指令。例如:
    curr_byte = read_byte()
    if curr_byte == 0x00:
       # Parse instruction with no arguments
       curr_instruction = DO_THING_A;
       args = NULL;
    elif curr_byte == 0x01:
       another_byte = read_byte()
       if another_byte == 0x00:
          # Parse a two-byte instruction
          curr_instruction = DO_THING_B;
          args = NULL;
       else:
          # Parse a one-byte instruction
          # with one argument
          curr_instruction = DO_THING_C;
          args = another_byte >> 1; # or whatever
    elif curr_byte == ...:
       ... # go on and on and on
    
  4. 字节码的全部意义在于它可以在几乎任何硬件上由另一个程序(解释器或虚拟机)执行。例如,为了在新硬件上获得 CPython 运行,您需要一个适用于该硬件的 C 工具链(编译器、链接器、汇编器等)和一堆 Python 可以调用来做 low-level 事情(分配内存、输出文本、进行网络连接等)。一旦你有了它,就可以编写可以执行字节码的 C 代码 - 就是这样。