监控 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() 进入的最后一个作用域。