モニタリング C API¶
バージョン 3.13 で追加。
拡張モジュールがイベントモニタリングシステムと連携する必要がある場合があります。
イベントの購読やコールバックの登録は、sys.monitoring が公開する Python API で行えます。
実行イベントの発生¶
以下の関数を使うと、拡張モジュールが Python コードの実行をエミュレートするときにモニタリングイベントを発生させられます。
各関数は、イベントの有効化状態を簡潔に保持する PyMonitoringState 構造体と、イベントの引数を受け取ります。
イベントの引数には、コードオブジェクトを表す PyObject*、命令オフセット、場合によってはイベント固有の追加引数が含まれます (各イベントのコールバックのシグネチャは sys.monitoring を参照してください)。
codelike 引数には、types.CodeType またはそれをエミュレートする型のインスタンスを指定してください。
VM はイベントを発生させるときにトレースを無効にするため、利用者のコードで無効にする必要はありません。
以下で現在の例外を扱うと記載された関数を除き、例外が設定された状態でモニタリング関数を呼び出してはいけません。
-
type PyMonitoringState¶
イベント種別の状態を表します。 利用者が領域を割り当て、内容は以下のモニタリング API 関数が管理します。
以下の関数はすべて、成功した場合は 0 を返し、エラーの場合は例外を設定して -1 を返します。
イベントの説明は sys.monitoring を参照してください。
-
int PyMonitoring_FirePyStartEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)¶
PY_STARTイベントを発生させます。
-
int PyMonitoring_FirePyResumeEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)¶
PY_RESUMEイベントを発生させます。
-
int PyMonitoring_FirePyReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval)¶
PY_RETURNイベントを発生させます。
-
int PyMonitoring_FirePyYieldEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval)¶
PY_YIELDイベントを発生させます。
-
int PyMonitoring_FireCallEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *callable, PyObject *arg0)¶
CALLイベントを発生させます。
-
int PyMonitoring_FireLineEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, int lineno)¶
LINEイベントを発生させます。
-
int PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset)¶
JUMPイベントを発生させます。
-
int PyMonitoring_FireBranchLeftEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset)¶
BRANCH_LEFTイベントを発生させます。
-
int PyMonitoring_FireBranchRightEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset)¶
BRANCH_RIGHTイベントを発生させます。
-
int PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval)¶
C_RETURNイベントを発生させます。
-
int PyMonitoring_FirePyThrowEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)¶
現在の例外 (
PyErr_GetRaisedException()が返すもの) を使ってPY_THROWイベントを発生させます。
-
int PyMonitoring_FireRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)¶
現在の例外 (
PyErr_GetRaisedException()が返すもの) を使ってRAISEイベントを発生させます。
-
int PyMonitoring_FireCRaiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)¶
現在の例外 (
PyErr_GetRaisedException()が返すもの) を使ってC_RAISEイベントを発生させます。
-
int PyMonitoring_FireReraiseEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)¶
現在の例外 (
PyErr_GetRaisedException()が返すもの) を使ってRERAISEイベントを発生させます。
-
int PyMonitoring_FireExceptionHandledEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)¶
現在の例外 (
PyErr_GetRaisedException()が返すもの) を使ってEXCEPTION_HANDLEDイベントを発生させます。
-
int PyMonitoring_FirePyUnwindEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset)¶
現在の例外 (
PyErr_GetRaisedException()が返すもの) を使ってPY_UNWINDイベントを発生させます。
-
int PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *value)¶
STOP_ITERATIONイベントを発生させます。valueがStopIterationのインスタンスなら、それを使います。 それ以外の場合は、valueを引数として新しいStopIterationインスタンスを作成します。
モニタリング状態の管理¶
モニタリング状態は、モニタリングスコープを使って管理できます。 通常、一つのスコープが一つの Python 関数に対応します。
-
int PyMonitoring_EnterScope(PyMonitoringState *state_array, uint64_t *version, const uint8_t *event_types, Py_ssize_t length)¶
モニタリング対象のスコープに入ります。
event_typesは、そのスコープから発生し得るイベントの ID の配列です。 例えばPY_STARTイベントの ID はPY_MONITORING_EVENT_PY_STARTで、この値はsys.monitoring.events.PY_STARTの 2 を底とする対数に等しくなります。state_arrayは、event_types内の各イベントに対応するモニタリング状態の配列です。 領域は利用者が割り当て、イベントの有効化状態はPyMonitoring_EnterScope()が設定します。event_types(したがってstate_arrayも) のサイズはlengthで指定します。version引数は、利用者がstate_arrayと一緒に領域を割り当て、0 に初期化しておく値へのポインタです。 その後はPyMonitoring_EnterScope()自身だけが値を設定するようにしてください。 この値によって、前回の呼び出し以降にイベントの状態が変化したかどうかを判断し、変化していなければ速やかに戻ることができます。ここでいうスコープは、関数、クラス、メソッドといった字句スコープです。 字句スコープに入るたびに
PyMonitoring_EnterScope()を呼び出してください。 再帰的な Python 関数をエミュレートする場合などは、同じstate_arrayとversionを再利用してスコープに再び入れます。 ジェネレータをエミュレートする場合など、コードに相当するオブジェクトの実行を一時停止するときは、スコープを一度出てから再び入る必要があります。event_typesに使うマクロは次のとおりです。マクロ
イベント
-
PY_MONITORING_EVENT_BRANCH_LEFT¶
-
PY_MONITORING_EVENT_BRANCH_RIGHT¶
-
PY_MONITORING_EVENT_CALL¶
-
PY_MONITORING_EVENT_C_RAISE¶
-
PY_MONITORING_EVENT_C_RETURN¶
-
PY_MONITORING_EVENT_EXCEPTION_HANDLED¶
-
PY_MONITORING_EVENT_INSTRUCTION¶
-
PY_MONITORING_EVENT_JUMP¶
-
PY_MONITORING_EVENT_LINE¶
-
PY_MONITORING_EVENT_PY_RESUME¶
-
PY_MONITORING_EVENT_PY_RETURN¶
-
PY_MONITORING_EVENT_PY_START¶
-
PY_MONITORING_EVENT_PY_THROW¶
-
PY_MONITORING_EVENT_PY_UNWIND¶
-
PY_MONITORING_EVENT_PY_YIELD¶
-
PY_MONITORING_EVENT_RAISE¶
-
PY_MONITORING_EVENT_RERAISE¶
-
PY_MONITORING_EVENT_STOP_ITERATION¶
-
PY_MONITORING_EVENT_BRANCH¶
バージョン 3.14 で非推奨: 代わりに
PY_MONITORING_EVENT_BRANCH_LEFTとPY_MONITORING_EVENT_BRANCH_RIGHTを使ってください。
-
PY_MONITORING_EVENT_BRANCH_LEFT¶
-
int PyMonitoring_ExitScope(void)¶
PyMonitoring_EnterScope()で最後に入ったスコープを出ます。
-
int PY_MONITORING_IS_INSTRUMENTED_EVENT(uint8_t ev)¶
イベント ID
evに対応するイベントが ローカルイベント の場合に真を返します。Added in version 3.13.
バージョン 3.14 で ソフト非推奨 <Soft deprecated>.