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 直譯式語言在作業系統中的運作方式!