Python のフレームオブジェクトとコールスタック

フレームオブジェクトは関数呼び出しの実行コンテキストを表し、コールスタックの情報を保持しています。デバッグやトレースに活用できます。

フレームの取得

import sys

def inner():
    frame = sys._getframe()
    print(f"Current function: {frame.f_code.co_name}")
    print(f"Caller: {frame.f_back.f_code.co_name}")

def outer():
    inner()

outer()

sys._getframe() で現在のフレームを取得し、f_back で呼び出し元のフレームを辿れます。

フレームの主要属性

f_codeコードオブジェクト
f_localsローカル変数の辞書
f_globalsグローバル変数の辞書
f_back呼び出し元のフレーム
f_lineno現在実行中の行番号
f_lasti最後に実行したバイトコードのインデックス

コールスタックの走査

import sys

def print_stack():
    frame = sys._getframe()
    while frame:
        code = frame.f_code
        print(f"{code.co_filename}:{frame.f_lineno} in {code.co_name}")
        frame = frame.f_back

def func_a():
    func_b()

def func_b():
    print_stack()

func_a()

ローカル変数の取得

def debug_locals():
    x = 10
    y = 20
    frame = sys._getframe()
    print(frame.f_locals)  # {'x': 10, 'y': 20, 'frame': ...}

debug_locals()

inspect モジュールとの連携

import inspect

def show_callers():
    for frame_info in inspect.stack():
        print(f"{frame_info.function} at line {frame_info.lineno}")

def example():
    show_callers()

example()

inspect.stack() は FrameInfo オブジェクトのリストを返し、より安全にスタック情報を取得できます。

注意点

フレームへの参照を保持すると循環参照が発生しやすい
sys._getframe() は CPython 固有で、他の実装では動作しない可能性がある
本番コードでの使用は避け、デバッグ用途に留める

フレームオブジェクトの理解は、デバッガーやプロファイラの実装、例外トレースバックの解析に不可欠です。