python-debugger について
python-debuggerは、Python開発者向けに、エラーの再現から原因特定、修正、検証までを案内するスキルです。トレースバック、pdb、ログ、プロファイリング、よくある原因を扱います。
主な機能
- 01段階的なデバッグ手順
- 02トレースバックの分析
- 03再現と切り分けの手法
- 04よくあるPythonエラーと修正方法
- 05ログとプロファイリングの案内
- 06pdbとエラー種類のリファレンス
活用シーン
- 01例外の発生箇所の追跡
- 02不具合を再現する最小ケースの作成
- 03pytestによる修正の検証
- 04性能やメモリ問題の調査
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ majesticlabs-dev/ majestic-marketplace --skill python-debuggerインストール後、Claude Code で/python-debuggerを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/debug-checklist.mdpdb-commands.mdpython-error-types.md詳細
Python デバッガー
デバッグのプロセス
- エラーを理解する -> 2. 再現する -> 3. 問題を切り分ける -> 4. 根本原因を特定する -> 5. 修正する -> 6. 検証する
ステップ 1:エラーを理解する
トレースバックを読む
Traceback (most recent call last): <- Read bottom to top
File "app.py", line 45, in main <- Entry point
result = process_data(data) <- Call chain
File "processor.py", line 23, in process_data
return transform(item) <- Getting closer
File "transformer.py", line 12, in transform
return item["value"] / item["count"] <- Error location
ZeroDivisionError: division by zero <- The actual error
一般的なエラーの種類については、references/python-error-types.md を参照してください。
ステップ 2:問題を再現する
エラーを引き起こす最小限のテストケースを作成します。次の質問に答えてください。
- どのような入力が原因でしたか?
- 毎回発生しますか、それとも断続的に発生しますか?
- いつから発生し始めましたか?
- 最近、何が変わりましたか?
ステップ 3:問題を切り分ける
print によるデバッグ
def process_data(data):
print(f"DEBUG: data type = {type(data)}")
print(f"DEBUG: data = {data}")
for i, item in enumerate(data):
print(f"DEBUG: processing item {i}: {item}")
result = transform(item)
print(f"DEBUG: result = {result}")
return results
pdb を使う
import pdb
def problematic_function(x):
pdb.set_trace() # Execution stops here
# Or use: breakpoint() # Python 3.7+
result = x * 2
return result
pdb のコマンドについては、references/pdb-commands.md を参照してください。
icecream を使う
from icecream import ic
def calculate(x, y):
ic(x, y) # Prints: ic| x: 5, y: 0
result = x / y
ic(result)
return result
ステップ 4:よくある根本原因
- None 値:属性にアクセスする前に戻り値を確認します。
if x is None: raise ValueError(...)でチェックします。 - 型の不一致:型ヒントを追加し、入力を明示的にキャストします。
a + bではなくint(a) + int(b)を使います。 - 変更可能なデフォルト引数:
def f(items=None):を使い、関数内でitems = items or []とします。 - 循環インポート:関数内で遅延インポートを使います:
from .module import Class - async/await:
awaitがないと、結果ではなくコルーチンが返されます。 - キー/インデックスのエラー:辞書には
.get(key, default)を使い、リストではlen()を確認します。 - スコープの問題:
global/nonlocalの宣言や、ループ内でのクロージャ変数のキャプチャを確認します。 - エンコーディング:
open()の呼び出しでencoding="utf-8"を指定します。 - 浮動小数点の精度:比較には
decimal.Decimalまたはmath.isclose()を使います。 - リソースリーク:ファイル、接続、ロックには
with文を使います。
ステップ 5:修正のパターン
防御的プログラミング
def safe_divide(a, b):
if b == 0:
raise ValueError("Cannot divide by zero")
return a / b
def safe_get(data: dict, key: str, default=None):
return data.get(key, default)
入力の検証
def process_user(user_id: int, data: dict) -> dict:
if not isinstance(user_id, int) or user_id <= 0:
raise ValueError(f"Invalid user_id: {user_id}")
required_fields = ["name", "email"]
missing = [f for f in required_fields if f not in data]
if missing:
raise ValueError(f"Missing required fields: {missing}")
例外処理
import logging
logger = logging.getLogger(__name__)
def fetch_user_data(user_id: int) -> dict:
try:
response = api_client.get(f"/users/{user_id}")
response.raise_for_status()
return response.json()
except requests.HTTPError as e:
logger.error(f"HTTP error fetching user {user_id}: {e}")
raise
except requests.ConnectionError:
logger.error(f"Connection failed for user {user_id}")
raise ServiceUnavailableError("API unavailable")
ステップ 6:修正を検証する
import pytest
def test_transform_handles_zero_count():
"""Verify fix for ZeroDivisionError."""
data = {"value": 10, "count": 0}
with pytest.raises(ValueError, match="count cannot be zero"):
transform(data)
def test_transform_normal_case():
"""Verify normal operation still works."""
data = {"value": 10, "count": 2}
result = transform(data)
assert result == 5
デバッグツール
ロギングの設定
import logging
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s %(name)s %(levelname)s: %(message)s",
handlers=[
logging.FileHandler("debug.log"),
logging.StreamHandler(),
],
)
プロファイリング
# Time profiling
import cProfile
cProfile.run("main()", "output.prof")
# Memory profiling
from memory_profiler import profile
@profile
def memory_heavy_function():
# ...
rich を使った見やすい出力
from rich.traceback import install
install(show_locals=True) # Enhanced tracebacks
参考資料
WebSearch を使う場面
- 分かりにくいエラーメッセージ
- ライブラリ固有のエラー
- バージョンの互換性に関する問題
- ドキュメントに記載されていない動作
コメント
Markdown 対応