Menu
CoddyTech

解释器是什么?

解释器是一种直接执行源代码的程序,它边读边执行其中的指令,而不是先把整个程序翻译成一个单独的机器码文件。Python 和 Ruby 的标准实现都是解释器。

作者 Kevin Spektor, 联合创始人兼 CTO

更新于 2026年9月24日

源代码
  1. 1print("Hello")
  2. 2total = 2 + 3
  3. 3print(total)
  4. 4print("Done")
输出
已翻译的行数0
运行次数0

每次运行都要重新翻译所有代码行。打开拼写错误后,解释器仍然会先输出“Hello”,到第 3 行才停下来。

输入 python3 hello.py,输出就出现了,但之后看看文件夹:并没有生成新的程序文件。真正运行的程序是 python3 本身,也就是 Python 解释器。它读取 hello.py,弄清每条语句的含义,然后执行它。明天再运行这个脚本,解释器又会从头读取一遍源代码。

解释器是如何工作的

解释器不断重复一个循环,直到程序结束:取出下一条指令,弄清它的含义,执行它,然后继续。工作过程中,它把程序的变量保存在自己的内存里,所以 total = price * 3 才能用上几行之前设置的 price。

最直观的观察方式是交互模式,也叫 REPL(读取、求值、打印、循环)。不带文件名输入 python3,每按一次回车,那一行就会立即运行:

>>> price = 4
>>> price * 3
12

真正的解释器还多了一个准备步骤。标准的 Python 解释器 CPython 会先把整个文件编译成字节码,也就是一串紧凑的简单指令,然后运行一个循环,每次执行一条字节码指令。你可以打印出一行代码对应的字节码:

Python 3.12 会打印出下面的内容(其他版本在细节上有所不同):

  0           0 RESUME                   0

  1           2 LOAD_NAME                0 (price)
              4 LOAD_CONST               0 (3)
              6 BINARY_OP                5 (*)
             10 STORE_NAME               1 (total)
             12 RETURN_CONST             1 (None)

其中每一行都是解释器循环中的一步:取出 price 的值,取出常量 3,把它们相乘,把结果存入 total。这些都不是机器码;执行每一步的是解释器,而解释器本身是一个编译好的 C 程序。

错误在那一行运行时才出现

由于解释器是边读边执行的,程序在遇到错误之前已经可以做一些实际的工作了。运行下面的代码,崩溃前会先打印出前两行:

Step 1: starting
Step 2: still fine
Traceback (most recent call last):
  ...
ZeroDivisionError: division by zero

语法错误的表现则不同,因为 CPython 在运行任何代码之前,会先把整个文件编译成字节码。把第 3 行改成 print("Step 3:" 10)(漏了逗号),就什么都不会打印,连 Step 1 也不会:

SyntaxError: invalid syntax. Perhaps you forgot a comma?

所以“解释器逐行运行代码”这种说法只对了一半。语法会先针对整个文件进行检查;其他错误,比如除以零或使用不存在的名字,只有在那一行执行时才会被发现。第一类错误请参阅语法错误。

编译器和解释器的区别

编译器在程序运行之前,把整个程序翻译成一个单独的文件。解释器则每次都亲自运行程序。两者在实际使用中的差异都由此而来:

编译器解释器
工作发生在何时程序运行前一次完成程序每次运行时都要做
输出一个单独的文件(可执行文件或字节码)没有单独的程序文件
交给用户的是什么编译好的程序源代码,外加用户电脑上安装的解释器
错误检查运行前检查整个程序的语法,在类型化语言中还检查类型错误通常先检查语法;其他错误在出错的那一行运行时才出现
修改后运行每次修改后都要重新编译保存后直接再次运行
速度更快,CPU 直接运行机器码更慢,每条指令都要在程序运行时解码
可移植性需要为每种 CPU 和操作系统重新编译同一份源代码在任何装有解释器的地方都能运行
典型语言C、C++、Rust、GoPython、Ruby、PHP、Bash

对于密集的算术循环,速度差距确实存在:同一个循环用编译后的 C 运行,可能比在 CPython 中快很多倍。但对于大部分时间都在等待网络、磁盘或用户的程序,这种差异往往小到察觉不出来。

编译型还是解释型,并不是语言本身的属性

语言是一套规则;编译器或解释器则是实现这些规则的程序。同一门语言可以用两种方式运行,而大多数流行语言都把两者结合了起来:

  • Python。 CPython 先编译成字节码,再解释执行。另一种实现 PyPy 加入了即时(JIT)编译器,在程序运行时把频繁执行的代码转换成机器码。
  • Java。 javac 提前把源代码编译成字节码。然后由 Java 虚拟机解释执行这些字节码,并把最繁忙的方法 JIT 编译成机器码。从 Java 11 开始,java Main.java 可以先在内存中编译单个源文件,然后直接运行它。
  • JavaScript。 浏览器和 Node.js 使用 V8 等引擎,它们一开始解释执行代码,并在程序运行过程中把热点部分编译成机器码。
  • C 和 C++。 几乎总是用 GCC、Clang 或 MSVC 提前编译。
python3 app.py            # Python: interpreter, bytecode behind the scenes
node app.js               # JavaScript: V8 interprets, then JIT-compiles
javac Main.java           # Java step 1: compile to Main.class
java Main                 # Java step 2: the JVM runs the bytecode

无论哪种情况,解释器或虚拟机都是程序运行时环境的一部分:程序在哪里运行,就必须在哪里安装它。

常见误解

  • “解释器把每一行都翻译成机器码。” 经典的解释器从来不会为你的程序生成机器码。它读取一条指令,然后用解释器中早已编译好的代码去执行它。在运行时生成机器码,是 JIT 编译器做的事。
  • “解释型语言没有编译步骤。” CPython、Ruby 的 YARV 和 PHP 都会先编译成字节码。这个步骤是自动且不可见的,所以很容易被忽略。
  • “解释型就意味着慢。” JIT 编译大大缩小了差距。V8 运行 JavaScript 的速度足以支撑大型应用,比如基于 Electron 构建的 VS Code。
  • “Python 就是解释器。” Python 是语言。CPython、PyPy 和 MicroPython 是它的不同解释器,它们在速度和支持的库上都可能不同。

下一步学什么

想了解对比的另一半,可以阅读编译器是什么,看看它如何把源代码变成机器码。运行时环境页面解释了解释器还会带来哪些东西。想亲自试试解释器,可以运行一个 Python 脚本,或者打开 Python 在线编辑器。

常见问题

Python 是编译器还是解释器?

Python 是一门语言;运行它的程序通常是 CPython,而 CPython 是一个解释器。CPython 会先自动把你的代码编译成字节码,再解释执行这些字节码。Python 还有其他实现,比如加入了 JIT 编译器的 PyPy。

C++ 是解释器还是编译器?

C++ 是一门语言,它几乎总是用 GCC、Clang 或 MSVC 这样的编译器提前编译。编译结果是针对某一种 CPU 和操作系统的原生可执行文件。C++ 也有交互式工具,但它们其实是在后台编译每一段代码。

解释器和编译器哪个更快?

编译后的程序通常运行得更快,因为 CPU 直接执行机器码,而不需要解释器逐步解码。解释器则启动更快,因为不需要单独的构建步骤。JVM 和 V8 使用的 JIT 编译器会在程序运行时编译最繁忙的代码,缩小了两者之间的差距。

REPL 是什么?
REPL(读取、求值、打印、循环)是一种交互式命令行,解释器会在你输入每一行后立即运行它并显示结果。不带文件名输入 python3 或 node 就能打开一个 REPL。它很适合在不创建文件的情况下快速验证一个小想法。
一门语言可以既是编译型又是解释型吗?
可以。编译型还是解释型描述的是语言的实现,而不是语言本身。Java 先由 javac 编译成字节码,再由 JVM 解释执行并进行 JIT 编译;Python 和 JavaScript 等语言也同时有解释器和编译器。
Coddy 编程语言插图

和 Coddy 一起学编程

开始