Trình thông dịch là gì?
Trình thông dịch (interpreter) là chương trình thực thi trực tiếp mã nguồn, làm theo từng lệnh trong lúc chạy, thay vì dịch toàn bộ chương trình ra một tệp mã máy riêng trước. Bản cài đặt chuẩn của Python và Ruby đều là trình thông dịch.
Cập nhật 24 tháng 9, 2026
- 1print("Hello")
- 2total = 2 + 3
- 3print(total)
- 4print("Done")
Mỗi lần chạy, các dòng lại được dịch từ đầu. Bật lỗi gõ sai lên, trình thông dịch vẫn in ra "Hello" rồi mới tới dòng 3 và dừng lại.
Gõ python3 hello.py và kết quả hiện ra, nhưng hãy nhìn vào thư mục sau đó: không có tệp chương trình mới nào được tạo. Chương trình thực sự chạy là chính python3, trình thông dịch Python. Nó đọc hello.py, hiểu từng câu lệnh nghĩa là gì và làm theo. Ngày mai chạy lại script đó, trình thông dịch lại đọc mã nguồn từ đầu.
Trình thông dịch hoạt động thế nào
Trình thông dịch lặp lại một chu trình cho đến khi chương trình kết thúc: lấy lệnh tiếp theo, hiểu nó nghĩa là gì, thực hiện, rồi chuyển sang lệnh sau. Trong lúc làm việc, nó giữ các biến của chương trình trong bộ nhớ của chính nó, vì vậy total = price * 3 có thể dùng price được gán vài dòng trước đó.
Cách dễ thấy nhất là chế độ tương tác, gọi là REPL (read, evaluate, print, loop). Gõ python3 không kèm tên tệp, và mỗi dòng chạy ngay khi bạn nhấn Enter:
>>> price = 4
>>> price * 3
12
Trình thông dịch thực tế có thêm một bước chuẩn bị. CPython, trình thông dịch Python chuẩn, trước tiên biên dịch cả tệp của bạn sang bytecode, một danh sách gọn gồm các lệnh đơn giản, rồi chạy một vòng lặp thực thi bytecode đó từng lệnh một. Bạn có thể in ra bytecode của một dòng:
Python 3.12 in ra như sau (các phiên bản khác có thể khác ở chi tiết):
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)
Mỗi dòng trên là một bước trong vòng lặp của trình thông dịch: lấy giá trị của price, lấy hằng số 3, nhân chúng lại, lưu kết quả vào total. Không dòng nào là mã máy; chính trình thông dịch, vốn là một chương trình C đã biên dịch, thực hiện từng bước.
Lỗi xuất hiện khi dòng đó chạy
Vì trình thông dịch thực thi tới đâu làm tới đó, chương trình có thể làm được việc thật trước khi gặp lỗi. Chạy đoạn này và hai dòng đầu được in ra trước khi chương trình dừng:
Step 1: starting
Step 2: still fine
Traceback (most recent call last):
...
ZeroDivisionError: division by zero
Lỗi cú pháp thì khác, vì CPython biên dịch cả tệp sang bytecode trước khi chạy bất kỳ phần nào. Đổi dòng 3 thành print("Step 3:" 10) (thiếu dấu phẩy) và sẽ không có gì được in ra, kể cả Step 1:
SyntaxError: invalid syntax. Perhaps you forgot a comma?
Vậy câu "trình thông dịch chạy code từng dòng một" chỉ đúng một nửa. Ngữ pháp được kiểm tra cho cả tệp trước; mọi lỗi khác, như chia cho 0 hay dùng một tên không tồn tại, chỉ bị phát hiện khi dòng đó thực thi. Xem lỗi cú pháp để hiểu loại lỗi thứ nhất.
Trình biên dịch và trình thông dịch
Trình biên dịch dịch toàn bộ chương trình ra một tệp riêng trước khi chạy. Trình thông dịch thì tự chạy chương trình, mỗi lần một lượt. Những khác biệt thực tế đều bắt nguồn từ đó:
| Trình biên dịch | Trình thông dịch | |
|---|---|---|
| Khi nào làm việc | Một lần, trước khi chương trình chạy | Mỗi lần chương trình chạy |
| Đầu ra | Một tệp riêng (tệp thực thi hoặc bytecode) | Không có tệp chương trình riêng |
| Thứ giao cho người dùng | Chương trình đã biên dịch | Mã nguồn, cùng trình thông dịch cài trên máy họ |
| Kiểm tra lỗi | Lỗi cú pháp và, với ngôn ngữ có kiểu tĩnh, lỗi kiểu cho cả chương trình trước khi chạy | Cú pháp thường được kiểm tra trước; các lỗi khác xuất hiện khi dòng lỗi chạy |
| Sửa rồi chạy | Biên dịch lại sau mỗi thay đổi | Lưu rồi chạy lại |
| Tốc độ | Nhanh hơn, CPU chạy mã máy trực tiếp | Chậm hơn, mỗi lệnh được giải mã trong lúc chương trình chạy |
| Tính di động | Biên dịch lại cho từng loại CPU và hệ điều hành | Cùng một mã nguồn chạy được ở mọi nơi có trình thông dịch |
| Ngôn ngữ tiêu biểu | C, C++, Rust, Go | Python, Ruby, PHP, Bash |
Chênh lệch tốc độ là có thật với các vòng lặp tính toán dày đặc: cùng một vòng lặp có thể chạy nhanh hơn nhiều lần khi viết bằng C đã biên dịch so với trong CPython. Với các chương trình chủ yếu chờ mạng, ổ đĩa hay người dùng, khác biệt thường nhỏ đến mức khó nhận ra.
Biên dịch hay thông dịch không phải là thuộc tính của ngôn ngữ
Ngôn ngữ là một bộ quy tắc; trình biên dịch hay trình thông dịch là chương trình hiện thực hóa các quy tắc đó. Cùng một ngôn ngữ có thể chạy theo cả hai cách, và hầu hết các ngôn ngữ phổ biến đều kết hợp cả hai:
- Python. CPython biên dịch sang bytecode rồi thông dịch nó. PyPy, một bản cài đặt khác, có thêm trình biên dịch just-in-time (JIT) biến phần code chạy thường xuyên thành mã máy ngay khi chương trình đang chạy.
- Java.
javacbiên dịch mã nguồn sang bytecode từ trước. Máy ảo Java (JVM) sau đó thông dịch bytecode và biên dịch JIT các phương thức chạy nhiều nhất sang mã máy. Từ Java 11,java Main.javachạy trực tiếp một tệp mã nguồn bằng cách biên dịch nó trong bộ nhớ trước. - JavaScript. Trình duyệt và Node.js dùng các engine như V8, ban đầu thông dịch code rồi biên dịch các phần chạy nhiều sang mã máy trong lúc chương trình chạy.
- C và C++. Gần như luôn được biên dịch trước bằng GCC, Clang hoặc 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
Dù là cách nào, trình thông dịch hay máy ảo cũng là một phần của môi trường thực thi của chương trình: nó phải được cài ở mọi nơi chương trình chạy.
Những hiểu lầm phổ biến
- "Trình thông dịch dịch từng dòng sang mã máy." Một trình thông dịch cổ điển không bao giờ tạo ra mã máy cho chương trình của bạn. Nó đọc một lệnh và thực hiện lệnh đó bằng code đã được biên dịch sẵn bên trong trình thông dịch. Tạo mã máy lúc chạy là việc của trình biên dịch JIT.
- "Ngôn ngữ thông dịch không có bước biên dịch." CPython, YARV của Ruby và PHP đều biên dịch sang bytecode trước. Bước này diễn ra tự động và vô hình, nên rất dễ bỏ qua.
- "Thông dịch nghĩa là chậm." Biên dịch JIT đã thu hẹp phần lớn khoảng cách. V8 chạy JavaScript đủ nhanh cho các ứng dụng lớn như VS Code, vốn được xây dựng trên Electron.
- "Python chính là trình thông dịch." Python là ngôn ngữ. CPython, PyPy và MicroPython là các trình thông dịch khác nhau cho nó, và chúng có thể khác nhau về tốc độ cũng như các thư viện được hỗ trợ.
Đọc tiếp
Để xem nửa còn lại của phép so sánh, hãy đọc trình biên dịch là gì và cách nó biến mã nguồn thành mã máy. Trang môi trường thực thi giải thích trình thông dịch còn mang theo những gì. Để tự thử một trình thông dịch, hãy chạy một script Python hoặc mở Python playground.
Câu hỏi thường gặp
Python là trình biên dịch hay trình thông dịch?
Python là một ngôn ngữ; chương trình chạy nó thường là CPython, một trình thông dịch. CPython tự động biên dịch code của bạn sang bytecode trước, rồi thông dịch bytecode đó. Ngoài ra còn có các bản cài đặt khác, như PyPy, có thêm trình biên dịch JIT.
C++ là trình thông dịch hay trình biên dịch?
C++ là một ngôn ngữ, và gần như luôn được biên dịch trước bằng trình biên dịch như GCC, Clang hoặc MSVC. Kết quả là một tệp thực thi gốc cho một loại CPU và hệ điều hành. Có những công cụ tương tác cho C++, nhưng chúng vẫn biên dịch từng đoạn code ở phía sau.
Trình thông dịch và trình biên dịch, cái nào nhanh hơn?
Chương trình đã biên dịch thường chạy nhanh hơn, vì CPU thực thi mã máy trực tiếp thay vì để trình thông dịch giải mã từng bước. Trình thông dịch thì khởi chạy nhanh hơn, vì không có bước build riêng. Trình biên dịch JIT, được JVM và V8 dùng, thu hẹp khoảng cách bằng cách biên dịch phần code chạy nhiều nhất ngay khi chương trình đang chạy.
REPL là gì?
python3 hoặc node mà không kèm tên tệp sẽ mở một REPL. Nó tiện để thử một ý tưởng nhỏ mà không cần tạo tệp.Một ngôn ngữ có thể vừa biên dịch vừa thông dịch không?
javac biên dịch sang bytecode, rồi JVM thông dịch và biên dịch JIT bytecode đó; còn với các ngôn ngữ như Python và JavaScript thì có cả trình thông dịch lẫn trình biên dịch.