Python 資料全景課 / 第一部分 建立心智模型 · M1

M1 環境

同一個 notebook,在你的電腦上可以執行,在別人的電腦上可能一開始就報錯。這個單元建立一個「在哪裏都一樣」的 Python 環境,並學會查出「現在執行的是哪一個 Python」。
約 45 分鐘安裝 1 次 · 練習 notebook 1 個先修:M0
學完本單元,你能夠:
  1. 說出直譯器、套件、虛擬環境各自是甚麼;
  2. 用 uv 建立課程專案,裝好 PyYAML 和 JupyterLab;
  3. 用 sys.executable 查出現在執行的是哪一個 Python;
  4. 分清 pyproject.toml、uv.lock、.venv 的用途,知道哪些要交給別人、哪些不用。

1「我的電腦上可以執行」為甚麼不夠 Why "it works on my machine" is not enough

M0 的練習裏有一行 import yaml。把同一個 notebook 拿到一部新電腦上執行,很可能第一格就出錯:

ModuleNotFoundError: No module named 'yaml'

程式沒有寫錯。出錯的原因是那部電腦的 Python 沒有安裝 yaml 這個套件。一段 Python 程式能不能執行,不只看程式本身,還要看它在哪一個 Python 上執行,以及那個 Python 裝了哪些套件。

這個單元要解決的就是這件事:讓每個學生、每部電腦都有同一套 Python 和同一套套件。

2三樣東西:直譯器、套件、虛擬環境 Interpreter, packages, virtual environment

名稱 它是甚麼 比喻
直譯器(interpreter) 執行 Python 程式的程式,即是你輸入 python 時啟動的那一個 廚房的爐頭
套件(package) 別人寫好、可以安裝來用的程式碼,例如讀 YAML 的 PyYAML 廚具和材料
虛擬環境(virtual environment) 一個專案專用的資料夾,裏面有一個直譯器和這個專案的套件 每道菜各自一個工作枱

為甚麼要虛擬環境?如果所有專案都把套件裝在同一個地方,甲專案要 2.0 版、乙專案要 1.0 版,兩者就會互相覆蓋。每個專案有自己的工作枱,就不會互相影響;工作枱弄亂了,拆掉重建也不影響其他專案。

本課用 uv 管理這三樣東西。它是一個工具,負責下載合適版本的 Python、為專案建立虛擬環境、安裝套件,而且在 Mac 和 Windows 上的命令完全一樣。

flowchart LR
    A["<b>uv init --bare</b><br/>pyproject.toml"] --> B["<b>uv add pyyaml jupyterlab</b><br/>uv.lock、.venv"]
    B --> C["<b>uv run jupyter lab</b><br/>JupyterLab 開啟"]
    classDef cmd fill:#ffffff,stroke:#d3d1cb,color:#37352f
    class A,B,C cmd
圖 1 用 uv 建立課程專案的三個步驟。每個方框的下半是這一步之後,專案資料夾裏多了甚麼。

3安裝 uv Install uv

uv 只要安裝一次。打開終端機(Mac:「終端機」App;Windows:開始選單搜尋「PowerShell」),輸入對應的命令:

Mac

curl -LsSf https://astral.sh/uv/install.sh | sh

Windows(PowerShell)

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

裝好後,關掉終端機再重新打開,然後確認:

uv --version

看到 uv 0. 開頭的版本號就成功了。

裝好了卻說找不到 uv

安裝程式會把 uv 的位置加進系統的搜尋路徑(PATH),但只對新開的終端機有效。看到 command not found: uv(Mac)或「無法辨識 uv」(Windows),先關掉終端機再開一次。

你不用另外安裝 Python。下一步 uv 發現電腦裏沒有合適的 Python 時,會自動下載一個。

4建立課程專案 Create the course project

整門課的練習都放在同一個專案資料夾裏。在終端機逐行輸入:

mkdir python-course
cd python-course
uv init --bare
uv add pyyaml jupyterlab

完成後,資料夾裏多了三樣東西:

名稱 是甚麼 要交給別人嗎?
pyproject.toml 專案的說明:需要哪個版本的 Python、直接用到哪些套件 要
uv.lock 鎖定檔:每一個套件(包括套件自己需要的套件)的準確版本 要
.venv/ 虛擬環境:直譯器和已安裝的套件 不用

pyproject.toml 是寫給人看的,打開它會看到你剛才加的兩個套件:

[project]
name = "python-course"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
    "jupyterlab>=4.6.4",
    "pyyaml>=6.0.3",
]

(版本號會隨你安裝的時間而不同。)

.venv 可以隨時刪除。下一次執行 uv run,uv 會按 uv.lock 重新建立一個一模一樣的。所以交給別人的是清單(pyproject.toml+uv.lock),不是 .venv 本身。對方在自己的電腦上執行 uv sync,就得到同一個環境。

重點

環境不是「裝好就算」,而是「寫得下來、重建得出」。pyproject.toml 和 uv.lock 就是那份寫下來的紀錄。

5哪一個 Python? Which Python?

同一部電腦上,常常不只一個 Python:作業系統可能自帶一個,你以前可能裝過 Anaconda 或從 python.org 下載過一個,現在 uv 又為專案準備了一個。在終端機輸入 python3,啟動的是哪一個,要看系統的搜尋路徑;而在專案資料夾裏用 uv run,啟動的一定是專案 .venv 裏的那一個。

圖 2 同一部電腦上的兩條路。直接輸入 python3,用的是搜尋路徑上第一個找到的 Python;在專案資料夾裏用 uv run,用的是 .venv 裏的 Python 和這個專案的套件。
圖 2 同一部電腦上的兩條路。直接輸入 python3,用的是搜尋路徑上第一個找到的 Python;在專案資料夾裏用 uv run,用的是 .venv 裏的 Python 和這個專案的套件。

要查出現在執行的是哪一個,用 sys.executable:

uv run python -c "import sys; print(sys.executable)"

輸出會是專案資料夾裏 .venv 下的路徑,例如:

/Users/you/python-course/.venv/bin/python        (Mac)
C:\Users\you\python-course\.venv\Scripts\python.exe   (Windows)

把命令開頭的 uv run 拿走,直接執行 python3 -c "…"(Windows 用 python),結果多半是另一條路徑,甚至找不到 Python。這就是 M1 開頭那個 ModuleNotFoundError 的真正原因:程式在一個沒有裝 yaml 的 Python 上執行。

在專案裏,一律用 uv run

uv run python、uv run jupyter lab:前面加上 uv run,就保證用的是專案的 Python 和套件。直接輸入 python、pip install 或 jupyter lab,用的是搜尋路徑上的那一個,裝的套件也會落到別處。

6開啟 JupyterLab Open JupyterLab

在專案資料夾裏執行:

uv run jupyter lab

瀏覽器會自動打開 JupyterLab,左邊的檔案列表就是專案資料夾。要停止時,回到終端機按 Ctrl+C。

在這裏打開的 notebook,用的就是專案 .venv 裏的 Python,所以 import yaml 一定成功。把 M0 的三個練習檔複製到這個資料夾,再執行一次 m0-first-look.ipynb,這次是在你自己的環境裏執行。

7容易混淆 Easily confused

這兩樣 分別
uv add 和 import uv add 在終端機執行,把套件安裝進環境;import 寫在程式裏,把已安裝的套件載入來用。沒有先安裝,import 就會報 ModuleNotFoundError。
套件名稱和 import 名稱 安裝時叫 pyyaml,程式裏寫 import yaml。兩者不一定相同,以套件的說明文件為準。
pyproject.toml 和 uv.lock 前者寫「要甚麼」(PyYAML 6 或以上),給人讀和改;後者寫「實際裝了甚麼」(PyYAML 6.0.3 和它需要的一切),由 uv 生成,不要手改。
全域安裝和虛擬環境 全域安裝把套件裝進搜尋路徑上那個 Python,所有專案共用;虛擬環境只屬於一個專案。本課一律用虛擬環境。
requirements.txt 和 pyproject.toml 別人的專案常用 requirements.txt 列出套件。收到這樣的檔案,在自己的專案裏用 uv add -r requirements.txt 安裝即可。
你可能會遇到 conda

理工科的課程和實驗室常用 Anaconda 或 Miniforge 裏的 conda。它和 uv 做的是同一類事:管理直譯器、套件和環境。兩者都可以用,但不要在同一個專案裏混用。本課統一用 uv。

8動手:查出你的 Python Hands-on: find your Python

  1. 按上面的步驟安裝 uv、建立 python-course 專案;
  2. 下載 m1-which-python.ipynb,放進 python-course 資料夾;
  3. 執行 uv run jupyter lab,打開這個 notebook,逐個 cell 執行。

notebook 會印出你正在用的 Python 的路徑和版本,以及環境裏裝了多少個套件。最後一題請你刪除 .venv 再重新開啟,親眼看看 uv 怎樣把環境重建出來。

工程線(選做)

m1-numpy-eng.ipynb:用 uv add numpy matplotlib 加入兩個科學計算套件,確認版本,再用 M0 的感測器讀數畫一張折線圖。最後把 pyproject.toml 和 uv.lock 複製到另一個資料夾,用 uv sync 重建出同一個環境。需要 M0 的 sensor.json。

下一步

M2 會深入 JupyterLab:notebook 和 kernel 的分別,以及為甚麼「執行次序」會令結果無法重現。