監控 C API

3.13 版本新增。

擴充套件可能需要與事件監控系統互動。可以透過 sys.monitoring 中公開的 Python API 完成訂閱事件和註冊回撥。

生成執行事件

以下函式使擴充套件可以模擬 Python 程式碼的執行來觸發監控事件。這些函式中的每一個都接受一個 PyMonitoringState 結構,其中包含有關事件啟用狀態的簡明資訊,以及事件引數,其中包括一個表示程式碼物件的 PyObject*、指令偏移量,有時還包括其他特定於事件的引數(有關不同事件回撥的簽名詳細資訊,請參閱 sys.monitoring)。codelike 引數應該是 types.CodeType 的例項,或者是一個模擬它的型別。

虛擬機器在觸發事件時停用跟蹤,因此使用者程式碼無需執行此操作。

不應在設定異常的情況下呼叫監控函式,除非下面列出的那些使用當前異常的函式。

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_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset)

觸發 BRANCH 事件。

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 事件。 如果 valueStopIteration 的一個例項,則使用它。 否則,將建立一個新的 StopIteration 例項,並將 value 作為其引數。

管理監控狀態

可以使用監控範圍來管理監控狀態。一個範圍通常對應於一個 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

BRANCH

PY_MONITORING_EVENT_CALL

CALL

PY_MONITORING_EVENT_C_RAISE

C_RAISE

PY_MONITORING_EVENT_C_RETURN

C_RETURN

PY_MONITORING_EVENT_EXCEPTION_HANDLED

EXCEPTION_HANDLED

PY_MONITORING_EVENT_INSTRUCTION

指令

PY_MONITORING_EVENT_JUMP

跳轉

PY_MONITORING_EVENT_LINE

PY_MONITORING_EVENT_PY_RESUME

PY_RESUME

PY_MONITORING_EVENT_PY_RETURN

PY_RETURN

PY_MONITORING_EVENT_PY_START

PY_START

PY_MONITORING_EVENT_PY_THROW

PY_THROW

PY_MONITORING_EVENT_PY_UNWIND

PY_UNWIND

PY_MONITORING_EVENT_PY_YIELD

PY_YIELD

PY_MONITORING_EVENT_RAISE

RAISE

PY_MONITORING_EVENT_RERAISE

RERAISE

PY_MONITORING_EVENT_STOP_ITERATION

STOP_ITERATION

int PyMonitoring_ExitScope(void)

退出使用 PyMonitoring_EnterScope() 進入的最後一個作用域。