見出し画像

[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に揃える)


診断 → 修正 → 再発防止(型で動く)

  1. 再現:10行以内の再現コードを作る(データも最小化)

  2. 観測:print(repr(x), type(x))(中身と型を必ず見る)

  3. 修正:入力側で正すか、関数側で防御するか決める

  4. 防止:テスト/型ヒント/ロガーで再発を抑える

例(型で守る):

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地獄は卒業

いいなと思ったら応援しよう!