恢復演練:診斷失敗的環境
獨立掌握檢查 — 評量作業期間不得使用 AI 輔助。若接受任何輔助必須如實申報,但接受輔助的作業只計為補救練習:在聲稱掌握之前,必須完成一次新的無輔助檢查。
前置要求
完成第 02 學習日各活動。評量路徑需要 Bash;已驗證的執行範圍是 Linux Bash。需要可用的 `python3`;不安裝套件、不做機器級更改。
學習目標
用預測、最小重現和恢復筆記,診斷一個被故意破壞的虛擬環境或路徑假設。
操作指引
本演練在一次性 env-drill 目錄內提供一個故意破壞但無害的裝置。執行前預測症狀,重現它,收集診斷證據,應用可論證的最小修正,然後複查。全程留在裝置目錄內;不做任何機器級更改(不安裝、不編輯 env-drill 以外的內容、不做持久環境改動——下面的修復只作用於單次命令呼叫)。 各程式碼區塊在失敗即停的子 shell 中執行:設定階段先驗證新建的 mktemp 私有根目錄,失敗會在寫入前中止;還會透過一個不執行模組程式碼的 importlib.util.find_spec 檢查來確認環境 Python 設定是否已能解析 helper,若能解析也會中止(預期失敗需要這一前提;該探針不匯入也不執行模組)。最後的程式碼區塊會印出一條字面 rm -r -- <private-root> 清理行,只指向所建立的根目錄。後續程式碼區塊之前先貼上印出的 export SBX_ROOT= 行;並記錄shell 原本 PYTHONPATH 的設定與否及其取值——未設定、空、非空都是有效證據。 請在 Bash 中執行這些程式碼區塊——印出的 export/rm -r -- 行使用 Bash 的 %q 引用,實際執行範圍為 Linux Bash;zsh/dash/Windows 未執行。
自主實作與記錄
建構損壞的裝置並重現失敗(整塊貼上;若設定失敗,或不執行模組的檢查發現 helper 已可解析,會在寫入前中止):
(
set -e
SBX_ROOT=$(mktemp -d "${TMPDIR:-/tmp}/d03env.XXXXXX")
[ -n "$SBX_ROOT" ]
[ -d "$SBX_ROOT" ]
[ -w "$SBX_ROOT" ]
[ -x "$SBX_ROOT" ]
probe_rc=0
python3 -c "import sys, importlib.util
try:
spec = importlib.util.find_spec('helper')
except Exception:
sys.exit(4)
sys.exit(3 if spec is not None else 0)" || probe_rc=$?
if [ "$probe_rc" -ne 0 ]; then
if [ "$probe_rc" -eq 3 ]; then
echo "abort: ambient Python config already resolves 'helper' - the intended failure cannot be demonstrated"
else
echo "abort: helper-resolvability probe failed (rc=$probe_rc) - cannot verify the precondition safely"
fi
exit 1
fi
mkdir "$SBX_ROOT/env-drill"
cd "$SBX_ROOT/env-drill"
mkdir tools
printf 'def greet():\n return "ok"\n' > tools/helper.py
printf 'from helper import greet\nprint(greet())\n' > app.py
rc=0
python3 app.py 2>err.txt || rc=$?
cat err.txt
grep -q "ModuleNotFoundError: No module named 'helper'" err.txt
echo "expected failure observed (rc=$rc)"
printf 'export SBX_ROOT=%q\n' "$SBX_ROOT"
)
執行前預測錯誤。貼上印出的 export SBX_ROOT= 行,然後收集證據:
(
set -e
: "${SBX_ROOT:?run the setup block first, then paste its printed export line}"
[ -d "$SBX_ROOT/env-drill" ]
cd "$SBX_ROOT/env-drill"
python3 -c "import sys, os; print([os.path.abspath(p or '.') for p in sys.path])"
ls tools
)
套用僅限本次呼叫的可論證最小修正並複查,將 PYTHONPATH 與記錄的原始值比較——程式碼區塊會印出明確的 set/unset 標記和取值,因此未設定、空、非空的原始狀態都可區別地證明未改變:
(
set -e
: "${SBX_ROOT:?run the setup block first, then paste its printed export line}"
[ -d "$SBX_ROOT/env-drill" ]
cd "$SBX_ROOT/env-drill"
pp_state() { if [ "${PYTHONPATH+x}" = x ]; then printf 'PYTHONPATH %s: set value=<%s>\n' "$1" "$PYTHONPATH"; else printf 'PYTHONPATH %s: unset\n' "$1"; fi }
pp_state before
PYTHONPATH=tools python3 app.py
pp_state after
printf 'rm -r -- %q\n' "$SBX_ROOT"
)
記錄症狀、證據、修復、為何最小的理由,以及複查結果。
Python 按 sys.path 搜尋——python3 app.py 時是腳本所在目錄,python3 -c 時是當前目錄。tools/ 兩者都不在,所以 from helper import greet 無法解析。PYTHONPATH=tools 只為那一次呼叫添加路徑;pp_state 行會印出明確的 set/unset 標記和取值,據此對比前後輸出以確認沒有持久化。PYTHONPATH 可以未設定、為空或已有值——三種情況下不變都證明無持久化。它是匯入搜尋變數,與可執行檔 PATH 無關。
觀察結果(Linux,Python 3.14):
1. 症狀:ModuleNotFoundError: No module named 'helper' — env-drill 在 sys.path 上,而 env-drill/tools 不在。
2. 證據:解析後的 sys.path 列表顯示 env-drill 和標準函式庫——沒有 env-drill/tools;ls tools 顯示 helper.py 存在——檔案在,但從腳本位置不可匯入。
3. 可論證的最小修復:PYTHONPATH=tools python3 app.py → ok。只為這次呼叫修正匯入路徑——不改檔案、不留持久環境改動(PYTHONPATH 前後輸出為記錄的原始值——未設定、空或相同的非空值;不變即證明無持久化)。移動 app.py 或編輯檔案都會改動過多。預期失敗還依賴一個環境前提,設定程式碼區塊不執行模組即可檢查並在不滿足時中止:helper 必須尚未可解析——importlib.util.find_spec 探針不匯入也不執行它(環境 PYTHONPATH 或 site-package 可能已能解析它)。
4. 複查:輸出 ok;裝置其餘部分不變。
Windows 參考資訊(未執行,也不是等價的限定寫法):cmd set PYTHONPATH=tools && python app.py 與 PowerShell $env:PYTHONPATH='tools'; python app.py 會為整個工作階段設定變數——要聲稱無持久化必須事後還原;單次呼叫限定需要另外的寫法。此處未驗證。
在無輔助條件下滿足以下全部即通過:(a) 執行前預測了 `ModuleNotFoundError` 症狀;(b) 記錄了診斷證據(缺少 `tools/` 的解析後 `sys.path` 列表,以及顯示檔案存在的 `ls tools` 結果);(c) 所應用的修復限定在單次呼叫內,並書面說明了為何最小;(d) 記錄了成功的複查和無持久化檢查——限定修復後的 `PYTHONPATH` 與記錄的原始值(未設定、空、或不變的非空值)一致。輔助只計為補救練習,在聲稱掌握之前必須完成一次新的無輔助檢查。
權威來源資源與權利證明
The Python Tutorial: Virtual Environments and Packages
對應章節 / 時間戳: Section 12 (creating venvs, pip installs, requirements files)
驗證版本與日期: Python 3.12 (Verified: 2026-10-30)
Primary reference for python -m venv, interpreter isolation, and requirements files used by the wrong-environment drills.
Basic Python syntax from Study Days 01-09
The drill needs no network: venv creation, sys.executable inspection, and ModuleNotFoundError reproduction all run offline.
對比候選資源與選型分析 (2)
Primary reference for pip commands, but the tutorial presents the create-activate-install loop as one beginner-friendly narrative.
Mature third-party environment tool with overlapping behavior; the stdlib venv tutorial was selected to avoid an extra dependency for first-time setup.
The Python Tutorial: Errors and Exceptions
對應章節 / 時間戳: Sections 8.3-8.6 (handling exceptions, else, finally, cleanup actions)
驗證版本與日期: Python 3.12 (Verified: 2026-10-30)
Primary reference for try/except/else/finally semantics and the with statement as predefined cleanup for Day 11.
Basic Python syntax from Study Days 01-09
Every clause behavior in the lesson is demonstrated by runnable local snippets.
對比候選資源與選型分析 (2)
Solid lecture treatment but paced for a semester course and requires video viewing; the tutorial section matches the exercise scope directly.
Reference-style exception hierarchy listing rather than the tutorial narrative; retained as lookup material for the recovery drills.