回復演習:壊れた環境を診断する
独立習得チェック — 評価対象の作業中に AI の支援は受けられません。支援を受けた場合は誠実に申告することが必須ですが、支援を受けた作業はあくまで復習扱いです。習得を主張する前に、新しい無支援チェックを完了してください。
前提条件
デイ 02 の活動の修了。評価対象の経路には Bash が必要です。検証済みの実行範囲は Linux Bash です。動作する `python3` が必要です。インストールもマシン全体の変更も不要です。
学習目標
意図的に壊した仮想環境またはパスの前提を、予測・最小再現・復習ノートで診断する。
手順
この演習では、使い捨ての env-drill ディレクトリ内に、意図的に壊れた無害なフィクスチャを用意します。実行前に症状を予測し、再現し、診断証拠を集め、正当化できる最小の修正を適用して、再チェックしてください。フィクスチャのディレクトリ内に留まり、マシン全体の変更は行いません(インストール、env-drill 外の編集、永続的な環境変更は禁止。下記の修正は1回のコマンド呼び出しに限定されています)。 各ブロックはフェイルストップのサブシェル内で実行します。セットアップは mktemp の新しい専用ルートを検証し、失敗時は書き込み前に中断します。周囲の Python 設定がすでに helper を解決できるかを、実行しない importlib.util.find_spec チェックで確認し、解決できる場合も中断します(意図した失敗にはその前提が必要で、このプローブはモジュールをインポートも実行もしません)。最後のブロックは、作成したルートを正確に指すリテラルな rm -r -- <private-root> 後片付け行を表示します。後続ブロックの前に表示された export SBX_ROOT= 行を貼り付け、シェル本来の 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 はその1回の呼び出しにだけ追加します。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) 適用した修正が1回の呼び出しに限定され、最小である理由を文書化した。(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.