10 min給工具使用者

Python 到底在哪裡跑?Anaconda、Jupyter、Terminal 與環境一次搞懂

從介面、Shell、Python interpreter、Jupyter kernel、environment、packages 到 working directory,學會用路徑與 runtime state 定位 Python 常見環境問題。

Aaron Huang系統、產品與 AI 實作

Python 到底在哪裡跑?Anaconda、Jupyter、Terminal 與環境一次搞懂

你可能遇過這種情況:

明明已經安裝 Python,Terminal 卻說找不到 python。

明明剛才在 Jupyter Notebook 可以 import 某個套件,換到 PowerShell 執行同一段程式卻出現錯誤。

甚至檔案就在電腦裡,Python 卻告訴你:

No such file or directory

新手很容易把這些問題全部理解成:

「是不是 Python 沒裝好?」

但很多時候,真正的問題不是「有沒有安裝」,而是:

你現在到底在哪個介面操作、是哪一個 Python 在執行、它屬於哪個環境、它看得到哪些套件,以及它目前站在哪個資料夾。

這也是學 Python 時很容易被忽略的一層。

你看到 Python、Anaconda、conda、Jupyter、kernel、Terminal、PowerShell 這麼多名字,好像每一個都在「跑 Python」。

其實不是。

先建立一張最重要的執行地圖

先不要急著背工具名稱。

一次 Python 程式執行,大致可以沿著這條路理解:

你
↓
操作介面
Terminal / Jupyter
↓
指令或 Notebook
PowerShell / Cell
↓
真正執行程式的人
Python interpreter / Jupyter kernel
↓
目前使用的環境
environment + packages
↓
目前所在位置
working directory + files
↓
輸出結果

真正重要的不是「我開的是哪個漂亮的畫面」,而是:

最後到底是哪個 Python 收到你的程式碼。

Python 執行層級與常見環境問題定位圖。

Python、Anaconda、Jupyter、Terminal 到底各自在做什麼?

我們先把最容易混在一起的名字拆開。

名稱 先把它理解成什麼 它是不是直接執行 Python 程式?
Python 程式語言,以及用來執行 Python 程式的 interpreter interpreter 會
Anaconda Python 發行與環境工具的一整組配置 不是「Anaconda 畫面」自己執行
conda 管理 environment 與 packages 的工具 主要負責管理,不是你的程式本身
Terminal 讓你輸入文字指令的操作介面 不是
PowerShell 讀取並處理終端機指令的 Shell 會啟動其他程式
Jupyter Notebook 互動式寫程式與查看結果的介面 本身透過 kernel 執行
kernel Notebook 背後真正執行程式碼的執行程序 是

這張表最重要的不是名詞定義,而是:

畫面不等於執行者。

你可以在 Jupyter 裡寫 Python,但真正執行 Cell 的是目前連上的 kernel。

你也可以在 Terminal 裡輸入:

python

但 Terminal 本身沒有突然變成 Python;它只是讓 Shell 去找到並啟動一個 Python interpreter。

這就是為什麼「我明明都在同一台電腦上」並不能保證兩邊正在使用同一個 Python。

第一個實驗:現在到底是哪個 Python 在跑?

這是之後碰到環境問題時,非常值得養成的第一個習慣:

不要猜,先看路徑。

在 Jupyter Notebook 裡執行:

import sys

print(sys.version)
print(sys.executable)

sys.version 讓你看到目前 Python 的版本。

更重要的是:

sys.executable

它會告訴你:

現在這段程式實際是由哪一個 Python executable 執行。

例如你可能看到類似:

C:\Users\...\anaconda3\envs\class\python.exe

這條路徑比一句:

「我應該是在用 Anaconda。」

可靠得多。

因為現在你有證據了。

如果接著你在 PowerShell 啟動 Python,再查看實際 executable,兩邊有可能相同,也有可能不同。

重點不是「一定要不同」。

重點是你開始知道:

我要確認的是執行者,而不是猜是哪個工具。

為什麼「套件明明裝了」卻不能 import?

這時候我們就可以解釋一個很常見的問題。

假設你的電腦上有:

Python A
└── Environment A
    └── package X

Python B
└── Environment B
    └── 沒有 package X

你曾經把 package X 裝進 Environment A。

現在你卻使用 Python B 執行:

import package_x

結果當然可能失敗。

所以「我有安裝這個套件」這句話其實少了一個重要資訊:

你把它安裝給哪個 Python 使用?

這也是 environment 存在的重要原因之一。

不同專案可能需要不同 Python 或不同 package 組合,因此工具會把它們隔離成不同環境。

因此之後看到:

ModuleNotFoundError

第一個問題不應該永遠是:

「我要不要重新安裝?」

而應該先問:

「現在是哪個 Python 在執行?」

接著再確認:

「這個環境裡到底有沒有我要的 package?」

conda 和 pip 又是什麼?

這也是很容易混亂的地方。

你可能看過:

conda install ...

也可能看過:

pip install ...

甚至:

python -m pip ...

這裡暫時不需要陷入「到底哪個比較好」。

Article 01 只需要先抓住一件事情:

安裝 package 時,要知道你正在替哪個 environment / Python 安裝。

因此像:

python -m pip

這種寫法的重要意義之一,就是讓「目前這個 python」去呼叫它所使用的 pip。

而 conda 則同時涉及 environment 與 package 的管理。

現在不用學會所有環境管理器。

這篇的停止線只是:

不要再把「我的電腦有裝」等同於「目前這個 Python 可以使用」。

第二個常見問題:檔案明明存在,為什麼 Python 說找不到?

這時問題可能已經不是 environment。

而是:

working directory。

假設你的電腦是:

learning/
├── data/
│   └── notes.json
└── app.py

你的程式裡寫:

open("data/notes.json")

這裡的:

data/notes.json

是相對路徑。

它不是在說:

「全世界幫我找一個叫 notes.json 的檔案。」

它是在說:

「從我目前的 working directory 出發,找 data/notes.json。」

所以即使檔案真的存在,只要你目前站的位置不同,相同指令仍可能得到不同結果。

這就是為什麼同一支程式:

在 A 資料夾執行 → 成功
在 B 資料夾執行 → 找不到檔案

完全有可能。

所以碰到:

FileNotFoundError

不要第一時間認定:

「檔案不見了。」

先確認:

程式目前是從哪個位置開始找?

Terminal 和 PowerShell 又差在哪?

這裡也可以順便拆掉一個常見混淆。

你看到的「黑色視窗」或 Terminal,本質上比較像一個讓你和命令列互動的介面。

而 PowerShell 是 Shell。

Shell 的工作之一,是理解你輸入的命令:

cd
python
conda

然後決定接下來要執行什麼。

因此:

Terminal

和:

PowerShell

並不是同一層的東西。

同樣地,當你輸入:

python

然後畫面變成:

>>>

你已經從 Shell 進入 Python 的互動環境。

這時:

cd

這類 Shell command,和:

print("hello")

這類 Python code,就不能再混為一談。

對新手來說,「我現在到底在哪一層」往往比多背十條 command 更重要。

Jupyter 更容易讓人忽略「狀態」

Notebook 還多了一個問題。

一般 .py 檔案很容易讓你形成這種直覺:

第一行
↓
第二行
↓
第三行

但 Notebook 的 Cell 可以自己決定執行順序。

假設 Cell 1:

score = 10

Cell 2:

print(score * 2)

你先執行 Cell 1,再執行 Cell 2:

20

看起來完全正常。

但如果你 restart kernel,直接執行 Cell 2:

NameError

原因很簡單:

新的 kernel 裡根本還沒有建立 score。

所以:

Notebook 畫面上還留著一個結果,不代表現在的 runtime state 仍然能產生那個結果。

你看到:

20

只能證明:

某個時間點曾經得到過 20。

它不一定證明:

現在從乾淨狀態重新執行,仍然可以得到 20。

所以 Notebook 一個非常重要的驗證方式就是:

Restart kernel
↓
從頭重新執行
↓
確認結果仍然能重現

把四種常見錯誤放回正確的層

現在再看最前面的幾個問題,就比較容易定位了。

現象 第一個該確認的方向
python 找不到 Shell 現在能不能找到 Python executable
套件裝過但 import 失敗 現在是哪個 Python / environment
檔案存在但找不到 working directory 與實際路徑
Notebook 剛才成功,重開卻失敗 kernel state 與 Cell 執行順序

你會發現,它們並不是同一種錯。

如果四種問題都只用:

重裝 Python

來解,很容易只是把原本的狀態變得更複雜。

比較可靠的順序是:

先觀察
↓
確認現在在哪一層
↓
找實際證據
↓
再決定修改什麼

到這裡,你真正需要會的是什麼?

Article 01 不要求你背大量 Terminal 指令,也不要求你一次精通 conda、pip、所有 environment manager。

你只需要能回答幾個問題:

我現在在哪個介面操作?

真正執行程式的是哪個 Python / kernel?

它屬於哪個 environment?

它看得到哪些 packages?

目前 working directory 在哪裡?

Notebook 現在的結果能不能從乾淨 kernel 重現?

只要你能開始用「實際路徑、環境與 runtime state」回答,而不是只說:

「我應該有裝。」

這篇的目的就達到了。

下一篇我們才會真正進入 Python 程式內部:

一筆資料進來之後,變數、型別、list、dict、if、for、function 到底怎麼一起把它變成結果?