11 / 90

Day 11: 異常與隔離環境

只捕捉你預期的異常,用 with 和 finally 保證清理,並在全新的虛擬環境中重現「在我機器上能跑」的故障——先診斷,再動手。 Retrieval and lower-new-content review are part of the 480-minute ledger.

Self-Directed Learning & Python 480 active minutes (8 hours focused study)
01 120 分鐘

精確的異常處理與有保證的清理

僅在記錄預測和觀察到的證據之後,才允許使用輔助。

Prerequisites

完成上一項活動;如遇阻塞,使用所列恢復連結。

Learning Objective

預測檔案開啟成功與拋出 FileNotFoundError 時 try、except、else、finally 各執行哪些子句,然後驗證。把手動 close() 換成 with 區塊,並解釋為什麼禁止裸 except。

Instructions

try 放有風險的呼叫。except FileNotFoundError as e 只處理這一種預期失敗,e.filename 給出遺失路徑。else 只在無異常時執行;finally 總是執行。裸 except: 被禁止,因為它連 KeyboardInterrupt 和真正的程式錯誤也會吞掉,讓診斷變成瞎猜。對檔案物件來說,with 是預先定義的清理動作,有了它 finally 就不再必要。

Practice & Prediction Log

在一個空的暫存資料夾中操作。把這個腳本執行兩次:第一次 notes.txt 不存在,第二次先用 printf 'hi\n' > notes.txt 建立它再執行。

try:
    f = open("notes.txt", encoding="utf-8")
except FileNotFoundError as e:
    print("cannot open", e.filename)
else:
    print("opened", f.name)
    f.close()
finally:
    print("cleanup")

每次執行前,寫下 try / except / else / finally 中哪些會執行以及確切輸出。然後 (1) 改寫成用 with 區塊關閉檔案,取代 else + f.close(),並展示區塊結束後 f.closed 為 True;(2) 舉出裸 except: 會隱藏的兩樣東西。

Independent Mastery Criterion

能準確說出成功與失敗各執行哪些子句,正確把 else/close() 改成 with 區塊,並舉出裸 except 會隱藏的兩樣東西。

Authoritative Source Resources & Provenance

linking PSF License Version 2

The Python Tutorial: Errors and Exceptions

作者 / 機構: Python Software Foundation | 原始出處連結 ↗

對應章節 / 時間戳: Sections 8.3–8.6 (handling exceptions, else, finally, cleanup actions)

驗證版本與日期: Python 3.12 documentation; verified 2026-10-30

入選理由:

Primary reference for try/except/else/finally semantics and the with statement as predefined cleanup.

來源前置條件:

安全回退方案(離線彈性):

Every clause behavior in the lesson is demonstrated by runnable local snippets.

對比候選資源與選型分析 (2)
MIT OCW 6.0001 Lecture on Exceptions ↗ compared_alternative [CC BY-NC-SA 4.0]

Solid lecture treatment, but paced for a semester course and requires video viewing; the tutorial section matches the exercise scope directly.

Python Standard Library: Built-in Exceptions ↗ compared_alternative [PSF License Version 2]

Reference-style exception hierarchy listing rather than the tutorial narrative; retained as lookup material for the recovery drills.

02 120 分鐘

故障診所:從 traceback 到定點修復

僅在記錄預測和觀察到的證據之後,才允許使用輔助。

Prerequisites

完成上一項活動;如遇阻塞,使用所列恢復連結。

Learning Objective

拿到一個在畸形分數行上崩潰的腳本,自下而上讀 traceback,指出故障行與異常類型,並套用最小修復:在 int() 周圍做定點 except ValueError,而不是包整個程式的捕捉。

Instructions

traceback 按呼叫從最舊到最新排列;最後一行給出異常類型和訊息:ValueError: invalid literal for int() with base 10: 'x9',其上方的幀指向 total += int(raw) 這一行。先用那一條壞行重現崩潰。最窄的修復只把 int(raw) 包進 try/except ValueError,記錄行號後繼續。把整個程式包進 except Exception 會藏住無關缺陷,還會把它們誤報成資料錯誤。

Practice & Prediction Log

在一個空的暫存資料夾中建立診所資料:

printf 'ana,7\nbo,x9\ncy,5\n' > scores.csv

把下面的程式碼儲存為 clinic.py:

total = 0
with open("scores.csv", encoding="utf-8") as fh:
    for lineno, line in enumerate(fh, start=1):
        name, raw = line.strip().split(",")
        total += int(raw)
print("total", total)

執行 python3 clinic.py,自下而上閱讀 traceback。記錄診斷:故障行、異常類型和最窄的修復。然後修改 clinic.py 讓它執行到結束,印出有效行的總和以及被跳過的行號。

Independent Mastery Criterion

診斷寫明故障位置與異常類型,依據異常層次解釋所選 except 類型為何是最窄的正確類型,並展示程式帶著跳過報告執行到結束。

Authoritative Source Resources & Provenance

linking PSF License Version 2

Python Standard Library: Built-in Exceptions

作者 / 機構: Python Software Foundation | 原始出處連結 ↗

對應章節 / 時間戳: Concrete exceptions and Exception hierarchy

驗證版本與日期: Python 3.12 documentation; verified 2026-10-30

入選理由:

Normative hierarchy used to justify the narrowest correct except clause during diagnosis.

來源前置條件:

安全回退方案(離線彈性):

The clinic traceback is reproduced locally; help(ValueError) documents the hierarchy offline.

對比候選資源與選型分析 (2)
W3Schools Python Exceptions ↗ compared_rejected_for_day11 [Proprietary]

Encourages broad except blocks; the clinic instead requires naming the exact hierarchy level.

The Python Tutorial: Errors and Exceptions ↗ compared_alternative [PSF License Version 2]

Friendlier first-pass narrative; the library reference was selected for the normative hierarchy the exercises name directly.

03 120 分鐘

用 venv 搭建隔離環境

僅在記錄預測和觀察到的證據之後,才允許使用輔助。

Prerequisites

完成上一項活動;如遇阻塞,使用所列恢復連結。

Learning Objective

在一個用完即棄的暫存資料夾中,用 python3 -m venv --without-pip .venv 建立虛擬環境,用 sys.executable 證明其直譯器與 python3 不同,展示只裝進 venv 的模組對 python3 不可見,並把依賴記錄到 requirements.txt。

Instructions

只在用完即棄的資料夾中操作,這樣觀察到的每個差異都是你親手製造的,而不是對自己機器的假設。命令適用於 Linux/macOS shell(Windows 上直譯器是 .venv\Scripts\python.exe;此處未執行)。不要啟用 venv:按路徑呼叫每個直譯器。

使用專用的一次性 shell/工作階段。建置和之後的所有步驟都在同一個 shell 中執行。建置中任何一步失敗都會結束該 shell;不要繼續。每次開啟新 shell 都必須重新執行建置程式碼區塊。建置後,繼續之前確認 pwd 顯示的是 $work。

work=$(mktemp -d) &&
cd "$work" &&
python3 -m venv --without-pip .venv || exit 1

之後的所有步驟都在同一個 shell 中執行;如果 echo "$work" 沒有輸出,先重新執行建置程式碼區塊。--without-pip 讓建立過程無需連網;新 venv 只帶標準函式庫。sys.executable 給出實際正在執行的直譯器。sysconfig.get_path('purelib') 給出該直譯器的 site-packages 資料夾(已安裝模組所在處),所以把一個單檔模組複製進去,就是一次無需網路、無需第三方套件的手工安裝。這只是教學用的捷徑,並非 pip 的做法:pip 還會寫入安裝中繼資料(.dist-info 資料夾),因此 pip 不會記錄這份手工複製,也無法解除安裝它。venv 的 pyvenv.cfg 寫著 include-system-site-packages = false:它不讀取基礎直譯器的 site-packages,其他直譯器也不讀取 venv 的。依賴以固定版本行寫進 requirements.txt(絕不放憑據),絕不提交 .venv。完成後:cd / && rm -rf "$work"。

Practice & Prediction Log

在 $work 中,執行前先預測每個結果。第 1 步:執行的是哪個直譯器?

python3 -c "import sys; print(sys.executable)"
.venv/bin/python -c "import sys; print(sys.executable)"

第 2 步:新建的 venv 能匯入 day11_helper 嗎?

.venv/bin/python -c "import day11_helper"

第 3 步:把一個單檔模組只裝進 venv,然後在其中匯入:

site=$(.venv/bin/python -c "import sysconfig; print(sysconfig.get_path('purelib'))")
printf 'def label():\n    return "helper from the venv"\n' > "$site/day11_helper.py"
.venv/bin/python -c "import day11_helper; print(day11_helper.label())"

第 4 步:python3 能匯入它嗎?

python3 -c "import day11_helper"

第 5 步:隔離證據,以及這個 venv 裡有沒有 pip:

grep include-system-site-packages .venv/pyvenv.cfg
.venv/bin/python -c "import sys; print(sys.prefix != sys.base_prefix)"
.venv/bin/python -m pip --version

第 6 步:記錄一個練習用的釘版(不要安裝;那需要 pip 和套件索引):

printf 'packaging==24.1\n' > requirements.txt
cat requirements.txt

針對第 2 步和第 4 步記錄診斷:應該改 import 行,還是改變環境?

Independent Mastery Criterion

能證明兩個直譯器路徑不同,在新建 venv 中重現 ModuleNotFoundError,並在模組只裝進 venv 後於 python3 下再次重現,且能根據 pyvenv.cfg 和 sys.prefix 解釋 venv 與其他直譯器為何互相看不到對方的 site-packages。

Authoritative Source Resources & Provenance

linking PSF License Version 2

The Python Tutorial: Virtual Environments and Packages

作者 / 機構: Python Software Foundation | 原始出處連結 ↗

對應章節 / 時間戳: Section 12 (Virtual Environments and Packages; creating venvs, pip, requirements)

驗證版本與日期: Python 3.12 documentation; verified 2026-10-30

入選理由:

Primary reference for python -m venv, interpreter isolation, and requirements files.

來源前置條件:

安全回退方案(離線彈性):

The drill needs no network: venv creation, sys.executable inspection, and ModuleNotFoundError reproduction all run offline.

對比候選資源與選型分析 (2)
pip documentation ↗ compared_alternative [MIT]

Primary reference for pip commands, but the tutorial section covers the create-activate-install loop as one narrative better suited to beginners.

virtualenv documentation ↗ compared_alternative [MIT License]

Mature third-party environment tool with overlapping behavior; the stdlib venv tutorial was selected to avoid an extra dependency for first-time setup.

04 120 分鐘

錯誤環境診斷演練

獨立掌握檢查(無 AI 輔助)。

Prerequisites

完成上一項活動;如遇阻塞,使用所列恢復連結。

Learning Objective

獨立診斷一個只在兩個受控直譯器之一下以 ModuleNotFoundError 失敗的腳本,給出 sys.executable 與 find_spec 證據及最小環境修復,然後把一次檔案讀取包進精確的 except 子句。

Instructions

閉卷。嚴格按下面搭建測試夾具;它保證只有 good 這個 venv 擁有該依賴(Linux/macOS shell,無需網路,無需第三方套件):

使用專用的一次性 shell/工作階段。建置和之後的所有步驟都在同一個 shell 中執行。建置中任何一步失敗都會結束該 shell;不要繼續。每次開啟新 shell 都必須重新執行建置程式碼區塊。建置後,繼續之前確認 pwd 顯示的是 $work。

work=$(mktemp -d) &&
cd "$work" &&
python3 -m venv --without-pip good &&
python3 -m venv --without-pip .venv &&
good_site=$(good/bin/python -c "import sysconfig; print(sysconfig.get_path('purelib'))") &&
printf 'def label():\n    return "report ok"\n' > "$good_site/day11_helper.py" &&
printf 'import day11_helper\nprint(day11_helper.label())\n' > report.py || exit 1

之後的所有步驟都在同一個 shell 中執行;如果 echo "$work" 沒有輸出,先重新執行建置程式碼區塊。症狀:.venv/bin/python report.py 拋出 ModuleNotFoundError: No module named 'day11_helper',而 good/bin/python report.py 正常。任務 1:從兩個直譯器收集證據(執行的是哪個直譯器、能否找到 day11_helper),記錄診斷,套用最小修復,並展示之後 .venv/bin/python report.py 印出 report ok。任務 2:撰寫 read_text(path),在 try/except FileNotFoundError 內以 encoding="utf-8" 開啟 path,檔案遺失時印出 missing 和 e.filename 而不是崩潰。完成後:cd / && rm -rf "$work"。

Practice & Prediction Log

記錄:(a) 兩個 sys.executable 值;(b) 每個直譯器能否找到 day11_helper;(c) 在 .venv/bin/python 下重現的 ModuleNotFoundError;(d) 診斷類別:程式故障還是環境故障;(e) 修復以及證明修復生效的輸出;(f) 你的 read_text 函式及其對 no_such_file.txt 的輸出。

Independent Mastery Criterion

獨立完成:診斷基於證據(來自兩個直譯器的 sys.executable,以及 find_spec 或 ModuleNotFoundError),修復針對這些證據所確定的原因並以 report ok 證明,檔案讀取恰好使用 except FileNotFoundError。

Authoritative Source Resources & Provenance

linking PSF License Version 2

The Python Tutorial: Virtual Environments and Packages

作者 / 機構: Python Software Foundation | 原始出處連結 ↗

對應章節 / 時間戳: Section 12 (Virtual Environments and Packages; creating venvs, pip, requirements)

驗證版本與日期: Python 3.12 documentation; verified 2026-10-30

入選理由:

Reference retained for the independent wrong-environment diagnosis assessment.

來源前置條件:

安全回退方案(離線彈性):

The assessment reproduces ModuleNotFoundError with the local interpreter only.

對比候選資源與選型分析 (2)
pip documentation ↗ compared_alternative [MIT]

Reference for install commands if the learner chooses the install-based fix.

virtualenv documentation ↗ compared_alternative [MIT License]

Mature third-party environment tool with overlapping behavior; the stdlib venv tutorial was selected to avoid an extra dependency for first-time setup.