Python được giải thích, hoặc biên dịch, hoặc cả hai?


190

Từ sự hiểu biết của tôi:

Một giải thích ngôn ngữ là một cấp cao chạy ngôn ngữ và được thực hiện bởi một thông dịch viên (một chương trình giúp chuyển đổi ngôn ngữ cấp cao sang mã máy và sau đó thực hiện) trên đường đi; nó xử lý chương trình một chút

Một biên soạn ngôn ngữ là một ngôn ngữ cấp cao mà mã là lần đầu tiên chuyển đổi sang máy mã bởi một trình biên dịch (một chương trình giúp chuyển đổi ngôn ngữ cấp cao sang mã máy) và sau đó được thực hiện bởi một người thi hành (một chương trình để chạy code).

Sửa tôi nếu định nghĩa của tôi sai.

Bây giờ trở lại với Python, tôi hơi bối rối về điều này. Ở mọi nơi bạn biết rằng Python là một ngôn ngữ được dịch, nhưng nó được hiểu theo một số mã trung gian (như mã byte hoặc IL) chứ không phải mã máy. Vì vậy, chương trình nào sau đó thực thi mã IM? Xin hãy giúp tôi hiểu cách xử lý và chạy tập lệnh Python.



2
Python không tạo các tệp .pyc (được gọi là mã phụ) mỗi khi thư viện được nhập. AFAIK mã byte chỉ có thể tăng tốc thời gian tải, không phải thời gian thực hiện.
Jesvin Jose

2
@aitchnyu: Bộ nhớ đệm mã byte trong các tệp .pyc chỉ tăng tốc độ tải thực sự, nhưng chỉ vì mã Python được biên dịch thành mã byte trước khi thực hiện. Mặc dù tôi không nghĩ rằng nó đã được thử với Python một cách cụ thể, nhưng các triển khai ngôn ngữ khác cho thấy mã byte thực sự dễ hiểu hơn so với AST đơn giản hoặc thậm chí tệ hơn, mã nguồn chưa được chỉnh sửa. Các phiên bản Ruby cũ hơn được giải thích từ AST, chẳng hạn, và AFAIK vượt trội hơn một chút so với các phiên bản mới hơn được biên dịch thành mã byte.

Không muốn nói thô lỗ, nhưng đó không phải là những gì tôi muốn nói (nhưng không được thông báo như bạn)?
Jesvin Jose

1
@aitchnyu: Tôi không biết ý của bạn là gì. Tôi chỉ biết rằng nhận xét của bạn không chính xác nhưng cung cấp độ chính xác tốt cho một số thông tin cơ bản tại sao nó chỉ tăng tốc thời gian tải, vì vậy tôi quyết định thêm thông tin đó. Không có ý xúc phạm hay thực hiện :)

Câu trả lời:


231

Trước hết, giải thích / biên dịch không phải là một tài sản của ngôn ngữ mà là một tài sản của việc thực hiện. Đối với hầu hết các ngôn ngữ, hầu hết nếu không phải tất cả các triển khai đều thuộc một loại, do đó, người ta có thể lưu một vài từ nói rằng ngôn ngữ cũng được diễn giải / biên dịch, nhưng nó vẫn là một sự khác biệt quan trọng, vì nó hỗ trợ sự hiểu biết và bởi vì có khá nhiều ngôn ngữ với các triển khai có thể sử dụng của cả hai loại (chủ yếu trong lĩnh vực ngôn ngữ chức năng, xem Haskell và ML). Ngoài ra, có các trình thông dịch và dự án C cố gắng biên dịch một tập hợp con của mã Python thành C hoặc C ++ (và sau đó là mã máy).

Thứ hai, quá trình biên dịch không bị giới hạn trong quá trình biên dịch trước thời hạn đối với mã máy gốc. Trình biên dịch nói chung là một chương trình chuyển đổi một chương trình trong một ngôn ngữ lập trình thành một chương trình bằng ngôn ngữ lập trình khác (có thể nói, bạn thậm chí có thể có một trình biên dịch có cùng ngôn ngữ đầu vào và đầu ra nếu áp dụng các phép biến đổi quan trọng). Và trình biên dịch JIT biên dịch thành mã máy gốc khi chạy , có thể cho tốc độ rất gần hoặc thậm chí tốt hơn so với biên dịch trước thời gian (tùy thuộc vào điểm chuẩn và chất lượng của việc triển khai so sánh).

Nhưng để ngăn chặn nitpicking và trả lời câu hỏi bạn muốn hỏi: Thực tế (đọc: sử dụng một triển khai có phần phổ biến và trưởng thành), Python được biên dịch . Không được biên dịch thành mã máy trước thời hạn (nghĩa là "được biên dịch" bởi hạn chế và sai, nhưng than ôi định nghĩa chung), "chỉ" được biên dịch thành mã byte , nhưng nó vẫn được biên dịch với ít nhất một số lợi ích. Ví dụ, câu lệnh a = b.c()được biên dịch thành một luồng byte, khi "tháo rời", trông giống như vậy load 0 (b); load_str 'c'; get_attr; call_function 0; store 1 (a). Đây là một sự đơn giản hóa, nó thực sự ít đọc hơn và mức độ thấp hơn một chút - bạn có thể thử nghiệm với dismô-đun thư viện tiêu chuẩn và xem giao dịch thực sự trông như thế nào.

Mã byte đó được giải thích (lưu ý rằng có một sự khác biệt, cả về lý thuyết và hiệu suất thực tế, giữa việc giải thích trực tiếp và lần đầu tiên biên dịch cho một số biểu diễn trung gian và diễn giải điều đó), như với cách triển khai tham chiếu (CPython), hoặc cả được diễn giải và biên dịch mã máy được tối ưu hóa trong thời gian chạy, như với PyPy .


2
Được rồi, điều này có nghĩa là một kịch bản python được biên dịch đầu tiên thành mã byte và sau đó nó được thực hiện bởi một trình thông dịch như CPython, Jython hoặc IronPython, v.v.
Pankaj Upadhyay

19
Không, nó được biên dịch thành mã byte và sau đó mã byte được thực thi bởi VM tương ứng. CPython vừa là trình biên dịch vừa là VM, nhưng Jython và IronPython chỉ là trình biên dịch.
Ignacio Vazquez-Abrams

1
@Igacio: Tôi không có nhiều kinh nghiệm với IronPython / Jython, nhưng ít nhất Jython có cung cấp lớp giống như trình thông dịch không? Tôi không tin rằng có thể thử biến Python thành mã byte JVM được gõ tĩnh. Tuy nhiên, điểm tốt về trình biên dịch và trình thông dịch là một phần của cùng một gói.

2
+1 "... một tài sản của việc thực hiện". Bản thân tôi đã nói "nó cho phép một lớp vỏ tương tác"
Jesvin Jose

2
@delnan: Chà, Jython hoạt động như một loại trung gian giữa ngôn ngữ Python và Java VM, nhưng nó biên dịch thành mã byte Java.
Ignacio Vazquez-Abrams

34

CPU chỉ có thể hiểu mã máy thực sự. Đối với các chương trình được giải thích, mục tiêu cuối cùng của một trình thông dịch là "diễn giải" mã chương trình thành mã máy. Tuy nhiên, thông thường một ngôn ngữ được giải thích hiện đại không giải thích trực tiếp mã con người vì nó quá kém hiệu quả.

Trình thông dịch Python trước tiên đọc mã con người và tối ưu hóa nó thành một số mã trung gian trước khi diễn giải nó thành mã máy. Đó là lý do tại sao bạn luôn cần một chương trình khác để chạy tập lệnh Python, không giống như trong C ++, nơi bạn có thể chạy mã thực thi được biên dịch trực tiếp. Ví dụ, c:\Python27\python.exehoặc /usr/bin/python.


11
Tôi thích quan điểm về việc "cần một chương trình khác để chạy [nó]". Điều đó đã giúp làm rõ một số suy nghĩ của tôi.
Matt

Vì vậy, python.exe đầu tiên tối ưu hóa mã và sau đó giải thích nó?
Koray Tugay

@KorayTugay, khi python.exe được cung cấp mã nguồn văn bản có thể đọc được của con người, trước tiên, nó tạo ra mã byte được tối ưu hóa, sau đó diễn giải điều đó (như bạn nói); tuy nhiên, khi đã có tệp mã byte (được biên dịch trước), nó không phải thực hiện bước đầu tiên, giúp tiết kiệm thời gian.
GordonBood

31

Câu trả lời phụ thuộc vào việc triển khai python đang được sử dụng. Nếu bạn đang sử dụng, hãy nói CPython (Việc triển khai tiêu chuẩn của python) hoặc Jython (Nhắm mục tiêu để tích hợp với ngôn ngữ lập trình java), trước tiên, nó được dịch sang mã byte và tùy thuộc vào việc triển khai python mà bạn đang sử dụng, mã này được hướng đến tương ứng máy ảo để giải thích . PVM (Máy ảo Python) cho CPython và JVM (Máy ảo Java) cho Jython.

Nhưng giả sử bạn đang sử dụng PyPy , một triển khai CPython tiêu chuẩn khác. Nó sẽ sử dụng Trình biên dịch đúng lúc .


Trong quá trình dịch sang mã byte, nó cần một trình biên dịch cái nào?
RICKY

Pypy là một triển khai Python , không phải là triển khai "CPython". Trên thực tế, Pypy là một thay thế cho CPython ( pypy.org/features.html ).
Giorgio

13

Theo trang web chính thức của Python, nó là một ngôn ngữ được giải thích.

https://www.python.org/doc/essays/blurb/

Python là ngôn ngữ lập trình cấp cao, hướng đối tượng, được giải thích ...

...

Vì không có bước biên dịch ...

...

Trình thông dịch Python và thư viện tiêu chuẩn mở rộng có sẵn ...

...

Thay vào đó, khi trình thông dịch phát hiện ra lỗi, nó sẽ đưa ra một ngoại lệ. Khi chương trình không bắt được ngoại lệ, trình thông dịch sẽ in dấu vết ngăn xếp.


7

Vâng, nó là cả ngôn ngữ biên dịch và giải thích. Vậy thì tại sao chúng ta thường gọi nó là ngôn ngữ diễn giải?

xem nó được biên dịch và giải thích như thế nào?

Trước hết tôi muốn nói rằng bạn sẽ thích câu trả lời của tôi hơn nếu bạn đến từ thế giới Java.

Trong Java, mã nguồn trước tiên được chuyển đổi thành mã byte thông qua trình biên dịch javac sau đó được chuyển hướng đến JVM (chịu trách nhiệm tạo mã gốc cho mục đích thực thi). Bây giờ tôi muốn cho bạn thấy rằng chúng tôi gọi Java là ngôn ngữ được biên dịch bởi vì chúng ta có thể thấy rằng nó thực sự biên dịch mã nguồn và cung cấp tệp. Class (không có gì ngoài mã byte) thông qua:

javac Hello.java -------> tạo tệp Hello. class

java Xin chào --------> Chuyển mã byte sang JVM cho mục đích thực thi

Điều tương tự cũng xảy ra với python, tức là đầu tiên mã nguồn được chuyển đổi sang mã byte thông qua trình biên dịch sau đó được chuyển đến PVM (chịu trách nhiệm tạo mã gốc cho mục đích thực thi). Bây giờ tôi muốn cho bạn thấy rằng chúng ta thường gọi Python là ngôn ngữ được dịch bởi vì quá trình biên dịch xảy ra đằng sau cảnh và khi chúng ta chạy mã python thông qua:

python Hello.py -------> trực tiếp mã hóa và chúng ta có thể thấy đầu ra chứng minh rằng mã là đúng về mặt cú pháp

@ python Hello.py có vẻ như nó trực tiếp thực thi nhưng thực sự đầu tiên nó tạo mã byte được phiên dịch bởi trình thông dịch để tạo mã gốc cho mục đích thực thi.

CPython - Chịu trách nhiệm về cả biên dịch và giải thích.

Nhìn vào các dòng dưới đây nếu bạn cần thêm chi tiết :

Như tôi đã đề cập rằng CPython biên dịch mã nguồn nhưng quá trình biên dịch thực sự xảy ra với sự trợ giúp của cython thì việc giải thích xảy ra với sự trợ giúp của CPython

Bây giờ chúng ta hãy nói một chút về vai trò của trình biên dịch đúng lúc trong Java và Python

Trong JVM, Trình thông dịch Java tồn tại để phiên dịch dòng mã byte theo từng dòng để lấy mã máy gốc cho mục đích thực thi nhưng khi mã byte Java được trình thông dịch thực thi, việc thực thi sẽ luôn chậm hơn. vậy giải pháp là gì? giải pháp là trình biên dịch Just-In-Time tạo ra mã gốc có thể được thực thi nhanh hơn nhiều so với trình biên dịch. Một số nhà cung cấp JVM sử dụng Trình thông dịch Java và một số sử dụng trình biên dịch Just-In-Time . Tham khảo: bấm vào đây

Trong python để có được xung quanh trình thông dịch để đạt được việc thực thi nhanh, hãy sử dụng một triển khai python khác ( PyPy ) thay vì CPython . bấm vào đây để thực hiện khác của python bao gồm PyPy .


6

If (Bạn biết Java) {

Mã Python được chuyển đổi thành mã byte giống như java.
Mã byte đó được thực hiện lại mỗi lần bạn cố gắng truy cập nó.

} other {

Mã Python ban đầu được sắp xếp thành một thứ gọi là mã byte
khá gần với ngôn ngữ máy nhưng không phải là mã máy thực tế
nên mỗi lần chúng ta truy cập hoặc chạy nó thì mã byte lại được thực thi lại

}


2

Hầu như, chúng ta có thể nói Python là ngôn ngữ được giải thích. Nhưng chúng tôi đang sử dụng một phần của quá trình biên dịch một lần trong python để chuyển đổi mã nguồn hoàn chỉnh thành mã byte như ngôn ngữ java.


1

Dành cho người mới

Python tự động biên dịch tập lệnh của bạn thành mã được biên dịch, được gọi là mã byte, trước khi chạy nó.

Chạy tập lệnh không được coi là nhập và không có .pyc sẽ được tạo.

Ví dụ: nếu bạn có tệp tập lệnh abc.py nhập mô-đun xyz.py khác, khi bạn chạy abc.py, xyz.pyc sẽ được tạo vì xyz được nhập, nhưng không có tệp abc.pyc nào được tạo kể từ abc. py không được nhập khẩu.


0

Mã python bạn viết được biên dịch thành mã python, tạo tệp với phần mở rộng .pyc. Nếu biên dịch, một lần nữa câu hỏi là, tại sao không biên dịch ngôn ngữ.

Lưu ý rằng đây không phải là biên dịch theo nghĩa truyền thống của từ này. Thông thường, chúng tôi nói rằng quá trình biên dịch đang sử dụng ngôn ngữ cấp cao và chuyển đổi nó thành mã máy. Nhưng nó là một tập hợp các loại. Được biên dịch thành mã trung gian không thành mã máy (Hy vọng bạn đã nhận được ngay).

Quay lại quy trình thực hiện, mã byte của bạn, hiện trong tệp pyc, được tạo trong bước biên dịch, sau đó được thực thi bởi các máy ảo thích hợp, trong trường hợp của chúng tôi, CPython VM Dấu thời gian (được gọi là số ma thuật) được sử dụng để xác thực xem có. Tập tin py có thay đổi hay không, tùy thuộc vào tập tin pyc mới được tạo. Nếu pyc là mã hiện tại thì nó chỉ cần bỏ qua bước biên dịch.


0

Python (trình thông dịch) được biên dịch .

Bằng chứng: Nó thậm chí sẽ không biên dịch mã của bạn nếu nó có lỗi cú pháp .

Ví dụ 1:

print("This should print") 
a = 9/0 

Đầu ra:

This should print
Traceback (most recent call last):
  File "p.py", line 2, in <module>
    a = 9/0
ZeroDivisionError: integer division or modulo by zero

Mã được biên dịch thành công. Dòng đầu tiên được thực thi ( print) dòng thứ hai ném ZeroDivisionError(lỗi thời gian chạy).

Ví dụ 2:

print("This should not print")
/0         

Đầu ra:

  File "p.py", line 2
    /0
    ^
SyntaxError: invalid syntax

Kết luận : Nếu tệp mã của bạn SyntaxErrorkhông chứa gì sẽ thực thi do quá trình biên dịch thất bại.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.