1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | 您對程式語言執行方式的觀察非常敏銳,特別是區分編譯式和直譯式語言,以及 Python `.py` 檔案執行和互動模式的差異。這兩個問題觸及了直譯器語言的核心運作機制,我很樂意為您詳細解釋。 --- ## 執行 Python (.py 檔) 的完整工作流程 當您在終端機中執行一個 Python `.py` 檔案時,整個過程會比編譯式語言的直接執行稍微複雜一些,因為多了一個「直譯器」的角色。 --- ### Python 的直譯器是什麼? **Python 直譯器**是一個特殊的程式,它的主要職責是**讀取並執行 Python 程式碼**。 * 它不像編譯器那樣將整個程式一次性轉換成機器碼。 * 相反,直譯器會逐行或逐塊地讀取您的 Python 程式碼,將其轉換成一種中間形式(通常是**位元碼 bytecode**),然後再執行這些位元碼。 最常用的 Python 直譯器是 **CPython**,它是用 C 語言實現的。當您安裝 Python 時,通常就是安裝了 CPython。其他直譯器還有 Jython(基於 Java)、IronPython(基於 .NET)、PyPy(專注於效能)等,但它們的底層機制都類似。 --- ### 從執行 `.py` 檔到結束的工作流程 假設您在終端機輸入 `python3 my_script.py`: 1. **Shell 解析命令並啟動 Python 直譯器** * 您在終端機(如 Bash)輸入 `python3 my_script.py`。 * Shell 解析這個命令,它會去 `$PATH` 環境變數中尋找 `python3` 這個可執行檔(也就是 Python 直譯器本身)。 * 找到 `python3` 後,Shell 會像執行任何其他可執行檔一樣,發出系統呼叫(`fork()` 和 `execve()`)給 **Kernel**,請求 Kernel 啟動 `python3` 這個程式。此時,`python3` 這個直譯器就成為一個新的程序。 2. **Python 直譯器載入並處理 `.py` 檔案** * Kernel 啟動 `python3` 程序後,CPU 的控制權就交給了 `python3` 的機器碼。 * `python3` 直譯器啟動後,它會讀取您傳給它的參數 `my_script.py`。 * 直譯器會打開 `my_script.py` 檔案,開始從頭到尾**讀取**您的 Python 原始程式碼。 3. **程式碼的編譯(到位元碼)與執行** * 直譯器會將 Python 原始碼**即時編譯 (Just-In-Time Compile)** 成一種中間形式,稱為 **Python 位元碼 (bytecode)**。這個過程發生在記憶體中,或有時會被快取為 `.pyc` 檔案。 * 這些位元碼並不是直接的機器碼,而是類似於「虛擬機器指令」的東西,專為 Python 的**虛擬機器 (Python Virtual Machine, PVM)** 所設計。 * PVM 會逐條執行這些位元碼。在執行位元碼的過程中,如果遇到需要執行系統操作(如讀寫檔案、網路通訊、輸出到螢幕等),PVM 會發出相應的**系統呼叫 (System Calls)** 給 **Kernel**。 4. **Kernel 處理系統呼叫並與硬體互動** * 當 PVM 發出系統呼叫時,控制權再次從 Python 程序切換到 **Kernel**。 * Kernel 在核心模式下執行 C 語言編寫的核心代碼,實際與硬體(如顯示器、硬碟等)互動,完成請求的操作。 * 操作完成後,Kernel 會將結果返回給 Python 程序。 5. **程式結束或中斷** * 當 `my_script.py` 中的所有 Python 程式碼都被執行完畢,或者遇到錯誤、或者您手動按下 `Ctrl+C` 時,Python 程序會發出 `exit()` 系統呼叫,告知 Kernel 結束。 * `Ctrl+C` 通常會發送一個 `SIGINT` 訊號給 Python 程序。Python 直譯器捕獲到這個訊號後,會中斷當前執行,並清理資源後退出。 * Kernel 清理該程序所佔用的資源,並將控制權交還給 Shell。 --- ## 執行 Python (實時互動模式 `>>>`) 的完整工作流程 當您直接在終端機輸入 `python3` 而進入 `>>>` 實時互動模式時,工作流程與執行 `.py` 檔案非常相似,但多了一個**即時互動迴圈 (Read-Eval-Print Loop, REPL)** 的特性。 1. **Shell 解析命令並啟動 Python 直譯器(REPL 模式)** * 您在終端機輸入 `python3`。 * Shell 尋找並啟動 `python3` 這個可執行檔(Python 直譯器)。 * 這次,因為沒有給定 `.py` 檔案作為參數,直譯器會進入其內建的**互動模式**。它會顯示 `>>>` 提示符,等待使用者輸入。 2. **REPL 迴圈:讀取、評估、輸出、循環 (Read-Eval-Print Loop)** * **讀取 (Read)**:直譯器等待您在 `>>>` 提示符後輸入一行或多行 Python 程式碼。 * **評估 (Eval)**:當您按下 Enter 後,直譯器會立即將您輸入的程式碼編譯成位元碼,然後由 PVM 執行這些位元碼。在這個過程中,如果您的程式碼需要與作業系統互動(如定義變數、計算結果、印出文字),PVM 會發出**系統呼叫**給 **Kernel**。 * **輸出 (Print)**:PVM 執行完畢後,如果您的程式碼有返回結果(例如您輸入 `1 + 2`),直譯器會將這個結果格式化並立即顯示在終端機上。 * **循環 (Loop)**:完成一次評估和輸出後,直譯器會再次顯示 `>>>` 提示符,等待您的下一個輸入。 3. **Kernel 處理系統呼叫與硬體互動** * 這個部分與執行 `.py` 檔案時完全相同。無論是在 REPL 模式還是執行腳本,Python 程序只要需要作業系統服務,就必須透過系統呼叫請求 Kernel 協助,由 Kernel 去與底層硬體溝通。 4. **會話結束** * 您可以輸入 `exit()` 或按下 `Ctrl+D` 來退出 REPL 模式。 * 直譯器收到退出指令或訊號後,會清理資源,發出 `exit()` 系統呼叫,並將控制權交還給 Shell。 --- ### 主要差異總結 * **`.py` 檔案執行:** 直譯器會一次性讀取整個腳本,或至少是較大塊的程式碼,然後開始執行。流程是預先定義好的。 * **互動模式:** 直譯器進入 REPL 模式,逐行接收您的輸入,即時執行並立即返回結果。它是一個不斷循環的過程,直到您明確退出。 希望這些詳細的解釋能幫助您更清楚地理解 Python 直譯式語言在作業系統中的運作方式! |
Direct link: https://paste.plurk.com/show/n8YDnBASVfNCo8AsjNpM