[AI基礎解説]Tracebackってなんだ?— 例外の読み方・直し方の型(保存版)
ねらい:エラー文(Traceback)を“3行で”読み、最短で原因→修正にたどり着く。
対象:AI/データ分析/WEBの初〜中級者、チーム開発を始めた個人。
ゴール:どこで・何が・なぜを即断し、再発しない直し方までできる。
TL;DR(Tracebackは3行で読む)
① 例外種:TypeError, KeyError など“カテゴリ”を知る
② メッセージ:一番下の例外メッセージが“直接原因”
③ 直す行:スタックの一番下に近い**“自分のコード行”**が最初に直す場所
Tracebackの構造(最短理解)
上から“呼び出しの旅路”、下に行くほど根っこ
最後に例外種: メッセージ
ネスト時は「During handling of the above exception…」で原因の連鎖が出る
超ミニ例
def area(w, h):
return w * h
print(area("3", 2))
実行結果(抜粋):
Traceback (most recent call last):
File "sample.py", line 4, in <module>
print(area("3", 2))
File "sample.py", line 2, in area
return w * h
TypeError: can't multiply sequence by non-int of type 'str'
読み方:
例外種:TypeError
メッセージ:文字列 × 非int は不可
直す行:return w * h(あるいは呼び出し元の引数をintに揃える)
診断 → 修正 → 再発防止(型で動く)
再現:10行以内の再現コードを作る(データも最小化)
観測:print(repr(x), type(x))(中身と型を必ず見る)
修正:入力側で正すか、関数側で防御するか決める
防止:テスト/型ヒント/ロガーで再発を抑える
例(型で守る):
def area(w: int, h: int) -> int:
if not isinstance(w, int) or not isinstance(h, int):
raise TypeError(f"w/h must be int: {type(w)=}, {type(h)=}")
return w * h
よく出る例外と“即対処”(表なし・箇条書き版)
ModuleNotFoundError: No module named 'xxx'
原因:その環境に未インストール、別環境に入っている
対処:仮想環境を有効化 → python -m pip install xxx
予防:プロジェクトごとにvenv/conda、requirements.txtで固定
ImportError: cannot import name 'X' from 'pkg'
原因:バージョン差/名前違い/循環import
対処:正しいモジュール名か確認、バージョン固定or上げ下げ
予防:循環避ける、from pkg import subに寄せる
NameError: name 'x' is not defined
原因:タイポ/スコープ外
対処:変数宣言・引数を見直し
予防:Linter(ruff)と型ヒントで検出
AttributeError: 'NoneType' object has no attribute 'x'
原因:None を想定外で受け取っている
対処:print(obj, type(obj))で中身確認、if obj is None:で分岐
予防:戻り値の契約(型ヒント/テスト)を明文化
TypeError(引数数/型)
原因:関数シグネチャ不一致
対処:定義と呼び出しを合わせる
予防:エディタの引数ヒント、型付け
ValueError: invalid literal for int()
原因:変換不可の値
対処:前処理で検証、例外処理
予防:入力バリデーションの徹底
IndexError: list index out of range
原因:範囲外アクセス
対処:if i < len(a):、for x in aに書き換え
予防:境界テスト
KeyError: 'k'
原因:辞書にキーがない
対処:if 'k' in d: / d.get('k')
予防:defaultdict や pydantic等でスキーマ化
FileNotFoundError / PermissionError
原因:パス違い/権限不足
対処:Path(__file__).parent基準で解決、保存先の権限確認
予防:pathlib統一、プロジェクト内のdata/等に固定
UnicodeDecodeError ('utf-8' codec...)
原因:文字コード不一致
対処:open(..., encoding="utf-8")
予防:取り込み元のエンコーディング合意
OSError: [Errno 98] Address already in use(Windowsは10048)
原因:ポート競合
対処:プロセス停止/ポート変更
予防:.envでポート可変化、lsof/netstatで監視
SyntaxError / IndentationError
原因:構文ミス/Tabとスペースの混在
対処:エディタでTab→スペース4に統一、フォーマッタ(black)
予防:pre-commitで整形を自動化
VS Codeで“止めて見る”最小セット
使い方
バグりそうな行に breakpoint() を置く
VS CodeでF5(Run/Debug)
変数/ウォッチ/コールスタックで現場を観測
設定(.vscode/launch.json 最小)
{
"version": "0.2.0",
"configurations": [{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
}]
}
例外を“正しく”捕まえる(広すぎるexcept禁止)
原則
捕まえる例外を限定する(広い except Exception: は最終手段)
ログを必ず残す(原因・入力・スタック)
握りつぶさない(必要なら再送出)
import logging, sys
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
handlers=[logging.StreamHandler(sys.stdout)],
)
log = logging.getLogger(__name__)
try:
run()
except (ValueError, KeyError) as e:
log.exception("Invalid input: %s", e) # スタック付き
raise
最小再現テンプレ(Issueや質問に添える用)
# repro.py
from __future__ import annotations
def run():
# ここに最小の再現コード(入出力は埋め込む)
pass
if __name__ == "__main__":
run()
環境情報も添付(コピペでOK)
python -V
python -c "import sys,platform;print(sys.executable);print(platform.platform())"
python -m pip freeze | sort
コマンド習慣で“迷子”にならない
どのPython/どのpipかを常に可視化
python -c "import sys;print(sys.executable)"
python -m pip --version
差分更新の前に状況を確認
python -m pip list -o
実行はモジュール経由
python -m pytest
python -m http.server 8000
まとめ(今日からの運用)
まずは3行読み(例外種・メッセージ・直す行)
最小再現 → 観測(repr/type) → 修正 → 予防(テスト/型/ログ)
迷ったらデバッガで止めて見る。print地獄は卒業
