#
8.2 プロファイルとトレース (profiling and tracing)

Python インタプリタは、プロファイル: 分析 (profile) や実行の トレース: 追跡 (trace) といった機能を組み込むために低水準の サポートを提供しています。このサポートは、プロファイルや デバッグ、適用範囲分析 (coverage analysis) ツールなどに使われます。

Python 2.2 になってから、この機能の実装は実質的に作り直され、 C から呼び出すためのインタフェースが追加されました。 この C インタフェースは、プロファイルやトレース作業時に、 Python レベルの呼び出し可能オブジェクトが呼び出されることによる オーバヘッドを避け、直接 C 関数呼び出しが行えるようにしています。 プロファイルやトレース機能の本質的な特性は変わっていません; インタフェースではとレース関数をスレッドごとにインストールでき、 トレース関数に報告される基本イベント (basic event) は以前の バージョンにおいて Python レベルのトレース関数で報告されていた ものと同じです。

`int (*Py_tracefunc)(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg)`
  `PyEval_SetProfile()` および `PyEval_SetTrace()` を使って登録できるトレース関数の形式です。最初のパラメタは オブジェクトで、登録関数に obj として渡されます。 frame はイベントが属している実行フレームオブジェクトで、 what は定数 `PyTrace_CALL`, `PyTrace_EXCEPT`, `PyTrace_LINE` あるいは `PyTrace_RETURN` のいずれかで、arg は what の値によって以下のように 異なります:

  what の値 | arg の意味
  --- | ---
  `PyTrace_CALL` | 常に `NULL`です。
  `PyTrace_EXCEPT` | `sys.exc_info()` の返す例外情報です。
  `PyTrace_LINE` | 常に `NULL`です。
  `PyTrace_RETURN` | 呼び出し側に返される予定の値です。

int `PyTrace_CALL`
  関数やメソッドが新たに呼び出されたり、ジェネレータが新たなエントリの 処理に入ったことを報告する際の、`Py_tracefunc` のwhat の 値です。イテレータやジェネレータ関数の生成は、対応するフレーム内の Python バイトコードに制御の委譲 (control transfer) が起こらない ため報告されないので注意してください。

int `PyTrace_EXCEPT`
  例外が送出された際の`Py_tracefunc` のwhat の値です。 現在実行されているフレームで例外がセットされ、何らかのバイトコードが 処理された後に、what にこの値がセットされた状態でコールバック 関数が呼び出されます。

  この結果、例外の伝播によって Python が呼び出しスタックを逆戻りする 際に、各フレームから処理が戻るごとにコールバック関数が呼び出されます。 トレース関数だけがこれらのイベントを受け取ります; プロファイラは この種のイベントを必要としません。

int `PyTrace_LINE`
  行番号イベントを報告するときに (プロファイル関数ではなく) トレース関数のwhat パラメタとして渡す値です。

int `PyTrace_RETURN`
  関数呼び出しが例外の伝播なしに返るときに `Py_tracefunc` 関数what パラメタとして渡す値です。

void `PyEval_SetProfile`( | Py_tracefunc func, PyObject *obj)

  プロファイル関数を func に設定します。obj パラメタは 関数の第一パラメタとして渡され、何らかの Python オブジェクトかまたは `NULL`になります。プロファイル関数がスレッド状態を維持する必要が あるなら、各々のスレッドに異なる obj を使うことで、状態を 記憶しておく便利でスレッドセーフな場所を提供できます。プロファイル 関数は、モニタされているイベントのうち、行番号イベントを除く全ての イベントに対して呼び出されます。

void `PyEval_SetTrace`( | Py_tracefunc func, PyObject *obj)

  トレース関数を func にセットします。 `PyEval_SetProfile()` に似ていますが、トレース関数は 行番号イベントを受け取る点が違います。