Documentation Python

Pythonのbreakpoint()関数は、コードの実行を一時停止し、インタラクティブなデバッガを起動するための組み込み関数です。Python 3.7以降で導入され、従来のpdb.set_trace()よりも柔軟で使いやすいデバッグ方法を提供します。

デバッグ方法の比較

方法Python特徴推奨度
breakpoint()3.7+環境変数で柔軟に制御可能⭐⭐⭐
pdb.set_trace()全て従来の標準的な方法⭐⭐
import pdb; pdb.pm()全て事後デバッグ用⭐⭐
IDE デバッガ-GUIで直感的⭐⭐⭐

breakpoint関数の基本

基本的な使い方

def calculate_total(items: list) -> int:
    """商品の合計金額を計算"""
    total = 0
    for item in items:
        price = item['price']
        quantity = item['quantity']
        subtotal = price * quantity

        breakpoint()  # ここで実行が停止

        total += subtotal
    return total

# 使用例
items = [
    {'name': 'りんご', 'price': 100, 'quantity': 3},
    {'name': 'みかん', 'price': 80, 'quantity': 5},
]
result = calculate_total(items)

デバッガが起動したら

> /path/to/script.py(10)calculate_total()
-> total += subtotal
(Pdb) p item
{'name': 'りんご', 'price': 100, 'quantity': 3}
(Pdb) p subtotal
300
(Pdb) p total
0
(Pdb) c  # 続行

pdbの基本コマンド

ナビゲーションコマンド

コマンド省略形説明
nextn次の行へ(関数内に入らない)
steps次の行へ(関数内に入る)
continuec次のbreakpointまで実行
returnr現在の関数を抜けるまで実行
untilunt指定行まで実行
quitqデバッガを終了

情報表示コマンド

コマンド省略形説明
print exprp expr式の値を表示
pp expr式の値をpretty print
listl現在位置周辺のコードを表示
longlistll現在の関数全体を表示
wherewスタックトレースを表示
argsa現在の関数の引数を表示

実行例

def debug_example():
    x = 10
    y = 20
    breakpoint()
    z = x + y
    return z

# 実行すると...
# (Pdb) l          # 現在位置のコードを表示
#   1     def debug_example():
#   2         x = 10
#   3         y = 20
#   4  ->     breakpoint()
#   5         z = x + y
#   6         return z

# (Pdb) p x        # 変数xの値を表示
# 10

# (Pdb) p x + y    # 式を評価
# 30

# (Pdb) n          # 次の行へ
# > (5)debug_example()
# -> z = x + y

# (Pdb) p z        # まだ定義されていない
# *** NameError: name 'z' is not defined

# (Pdb) n          # もう一度次へ
# (Pdb) p z        # これで定義された
# 30

ブレークポイントの制御

動的なブレークポイント設定

# デバッガ内でブレークポイントを設定
# (Pdb) break 10              # 10行目にブレークポイント
# (Pdb) break function_name   # 関数の先頭にブレークポイント
# (Pdb) break file.py:20      # 別ファイルの20行目に
# (Pdb) break 10, x > 5       # 条件付きブレークポイント

# ブレークポイントの確認と削除
# (Pdb) break                 # 全ブレークポイントを表示
# (Pdb) clear 1               # ブレークポイント1を削除
# (Pdb) disable 1             # ブレークポイント1を無効化
# (Pdb) enable 1              # ブレークポイント1を有効化

条件付きbreakpoint

def process_items(items: list) -> list:
    """アイテムを処理"""
    results = []
    for i, item in enumerate(items):
        # 特定の条件でのみ停止
        if item < 0:
            breakpoint()  # 負の値のときだけ調査

        results.append(item * 2)
    return results

# 使用例
data = [1, 2, -3, 4, -5]
process_items(data)

プログラム的な条件付きブレーク

import sys

def conditional_break(condition: bool = True):
    """条件に応じてbreakpointを呼び出す"""
    if condition:
        breakpoint()

def process_data(data: list):
    for item in data:
        # デバッグモードのときだけ停止
        conditional_break('--debug' in sys.argv)
        print(f"Processing: {item}")

環境変数による制御

PYTHONBREAKPOINT環境変数

# デフォルト(pdbを使用)
python script.py

# breakpoint()を無効化
PYTHONBREAKPOINT=0 python script.py

# ipdbを使用(事前にpip install ipdbが必要)
PYTHONBREAKPOINT=ipdb.set_trace python script.py

# pudbを使用(事前にpip install pudbが必要)
PYTHONBREAKPOINT=pudb.set_trace python script.py

# カスタム関数を使用
PYTHONBREAKPOINT=mymodule.custom_debugger python script.py

プログラム内での制御

import sys
import os

def setup_debug_mode(enable: bool = True):
    """デバッグモードを設定"""
    if enable:
        # デフォルトのpdbを使用
        os.environ.pop('PYTHONBREAKPOINT', None)
    else:
        # breakpointを無効化
        os.environ['PYTHONBREAKPOINT'] = '0'

# 使用例
setup_debug_mode(False)  # 本番環境
breakpoint()  # 何も起きない

setup_debug_mode(True)   # 開発環境
breakpoint()  # pdbが起動

sys.breakpointhookのカスタマイズ

import sys

def custom_breakpoint(*args, **kwargs):
    """カスタムブレークポイント処理"""
    print("=" * 50)
    print("デバッグモードに入りました")
    print(f"引数: args={args}, kwargs={kwargs}")
    print("=" * 50)

    # 元のpdbを呼び出す
    import pdb
    pdb.set_trace()

# カスタムフックを設定
sys.breakpointhook = custom_breakpoint

# 使用例
def test_function():
    x = 10
    breakpoint()  # カスタムメッセージが表示される
    return x

test_function()

実践的なデバッグパターン

例外発生箇所の調査

def risky_operation(data: dict) -> str:
    """例外が発生する可能性のある処理"""
    try:
        result = data['key']['nested']
        return str(result)
    except (KeyError, TypeError) as e:
        # 例外発生時にデバッグ
        breakpoint()
        raise

# 使用例
try:
    risky_operation({'key': None})
except:
    pass

事後デバッグ(Post-mortem debugging)

import pdb

def failing_function():
    x = [1, 2, 3]
    return x[10]  # IndexError

# 方法1: tryで囲む
try:
    failing_function()
except:
    pdb.post_mortem()  # 例外発生時点の状態でデバッグ

# 方法2: -mオプション
# python -m pdb script.py
# 例外発生時に自動的にデバッガが起動

ループのデバッグ

def find_anomaly(data: list) -> list:
    """異常値を検出"""
    anomalies = []

    for i, value in enumerate(data):
        is_anomaly = value > 100 or value < 0

        # 異常値を見つけたときだけ停止
        if is_anomaly:
            print(f"異常値を検出: index={i}, value={value}")
            breakpoint()
            anomalies.append((i, value))

    return anomalies

# 使用例
data = [10, 20, 150, 30, -5, 40]
find_anomaly(data)

再帰関数のデバッグ

def factorial(n: int, depth: int = 0) -> int:
    """階乗を計算(デバッグ付き)"""
    indent = "  " * depth

    # 特定の深さで停止
    if depth == 3:
        print(f"{indent}depth=3に到達")
        breakpoint()

    if n <= 1:
        return 1

    result = n * factorial(n - 1, depth + 1)
    return result

# 使用例
factorial(5)

クラスメソッドのデバッグ

class DataProcessor:
    """データ処理クラス"""

    def __init__(self, data: list):
        self.data = data
        self.processed = False

    def process(self) -> list:
        """データを処理"""
        results = []

        for item in self.data:
            # 処理の途中経過を確認
            transformed = self._transform(item)

            if transformed is None:
                breakpoint()  # 変換失敗を調査

            results.append(transformed)

        self.processed = True
        return results

    def _transform(self, item):
        """アイテムを変換"""
        if isinstance(item, (int, float)):
            return item * 2
        return None

# 使用例
processor = DataProcessor([1, 2, "invalid", 4])
processor.process()

デバッグのベストプラクティス

本番環境での無効化

import os

# 方法1: 環境変数で制御
DEBUG = os.getenv('DEBUG', 'false').lower() == 'true'

def debug_break():
    """デバッグ環境でのみbreakpoint"""
    if DEBUG:
        breakpoint()

# 方法2: 設定ファイルで制御
class Config:
    DEBUG = False

def safe_breakpoint():
    if Config.DEBUG:
        breakpoint()

ロギングとの併用

import logging

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

def debug_with_logging(data: dict):
    """ロギングとデバッグを併用"""
    logger.debug(f"入力データ: {data}")

    try:
        result = process(data)
        logger.debug(f"処理結果: {result}")
        return result
    except Exception as e:
        logger.error(f"エラー発生: {e}")
        breakpoint()  # エラー時にデバッグ
        raise

def process(data: dict) -> str:
    return data['key']

デバッグ用ヘルパー関数

def debug_info():
    """デバッグ情報を表示するヘルパー"""
    import sys
    frame = sys._getframe(1)

    print("=" * 60)
    print(f"ファイル: {frame.f_code.co_filename}")
    print(f"関数: {frame.f_code.co_name}")
    print(f"行番号: {frame.f_lineno}")
    print(f"ローカル変数: {list(frame.f_locals.keys())}")
    print("=" * 60)

    breakpoint()

# 使用例
def my_function():
    x = 10
    y = 20
    debug_info()  # 詳細情報を表示してからデバッグ開始
    return x + y

IDE統合

VS Code

// launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Current File",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal",
            "justMyCode": false
        }
    ]
}

PyCharm

PyCharmでは、breakpoint()の代わりにGUIでブレークポイントを設定できます。 ただし、breakpoint()も正常に動作し、PyCharmのデバッガと統合されます。

注意点

本番コードからの削除

# 開発時
def process_data(data):
    result = transform(data)
    breakpoint()  # 開発中のデバッグ
    return result

# リリース前に削除
def process_data(data):
    result = transform(data)
    return result

grepで検索して削除

# breakpointの残存を確認
grep -r "breakpoint()" --include="*.py" src/

# 自動で削除(注意して使用)
sed -i '/breakpoint()/d' **/*.py

まとめ

操作方法
デバッグ開始breakpoint()
無効化PYTHONBREAKPOINT=0
次の行へn
関数内へs
続行c
変数表示p variable
終了q

breakpoint()関数は、Python 3.7以降で推奨されるデバッグ方法です。環境変数による柔軟な制御が可能で、開発・テスト・本番環境それぞれに適した設定ができます。

参考文献

円