监控 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_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 事件。如果 valueStopIteration 的实例,则使用它。否则,将使用 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

BRANCH_LEFT

PY_MONITORING_EVENT_BRANCH_RIGHT

BRANCH_RIGHT

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

INSTRUCTION

PY_MONITORING_EVENT_JUMP

JUMP

PY_MONITORING_EVENT_LINE

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() 进入的范围。

int PY_MONITORING_IS_INSTRUMENTED_EVENT(uint8_t ev)

如果与事件 ID *ev* 对应的事件是本地事件,则返回 true。

在 3.13 版本加入。

从 3.14 版本开始已弃用: 此函数是 软弃用 的。