yohhoyの日記

技術的メモをしていきたい日記

関数呼び出しのトレース

Pythonスクリプトにおいて、非侵襲的に関数呼び出しと戻り値をトレースする方法。

#!/bin/usr/env python3
import inspect
import sys

def tracer(frame, event, arg, depth=[0]):
  f_name = frame.f_code.co_name
  if f_name == '_ag':  # dirty hack for CPython 3.6+
    return

  if event == 'call':
    depth[0] += 1
    print('>' * depth[0], f_name, inspect.formatargvalues(*inspect.getargvalues(frame)))
    return tracer
  elif event == 'return':
    print('<' * depth[0], f_name, arg)
    depth[0] -= 1

sys.settrace(tracer)
# 以降の関数呼び出しをトレース対象とする

def fib(n):
  if n <= 2:
    return 1
  return fib(n - 1) + fib(n - 2)

result = fib(5)

出力結果:

> fib (n=5)
>> fib (n=4)
>>> fib (n=3)
>>>> fib (n=2)
<<<< fib 1
>>>> fib (n=1)
<<<< fib 1
<<< fib 2
>>> fib (n=2)
<<< fib 1
<< fib 3
>> fib (n=3)
>>> fib (n=2)
<<< fib 1
>>> fib (n=1)
<<< fib 1
<< fib 2
< fib 5

関連URL