特征分析与追踪

Python 解释器为附加的性能分析和执行跟踪工具提供了一些低层级的支持。它们可被用于性能分析、调试和覆盖分析工具。

这个 C 接口允许性能分析或跟踪代码避免调用 Python 层级的可调用对象带来的开销,它能直接执行 C 函数调用。 此工具的基本属性没有变化;这个接口允许针对每个线程安装跟踪函数,并且向跟踪函数报告的基本事件与之前版本中向 Python 层级跟踪函数报告的事件相同。

typedef int (*Py_tracefunc)(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg)

使用 PyEval_SetProfile() 和 PyEval_SetTrace() 注册的跟踪函数的类型。 第一个形参是作为 obj 传递给注册函数的对象,frame 是与事件相关的帧对象,what 是常量 PyTrace_CALL, PyTrace_EXCEPTION, PyTrace_LINE, PyTrace_RETURN, PyTrace_C_CALL, PyTrace_C_EXCEPTION, PyTrace_C_RETURN 或 PyTrace_OPCODE 中的一个,而 arg 将依赖于 what 的值:

what 的值

arg 的含义

PyTrace_CALL

总是 Py_None.

PyTrace_EXCEPTION

sys.exc_info() 返回的异常信息。

PyTrace_LINE

总是 Py_None.

PyTrace_RETURN

返回给调用方的值,或者如果是由异常导致的则返回 NULL。

PyTrace_C_CALL

正在调用函数对象。

PyTrace_C_EXCEPTION

正在调用函数对象。

PyTrace_C_RETURN

正在调用函数对象。

PyTrace_OPCODE

总是 Py_None.

int PyTrace_CALL

当对一个函数或方法的新调用被报告,或是向一个生成器增加新条目时传给 Py_tracefunc 函数的 what 形参的值。 请注意针对生成器函数的迭代器的创建情况不会被报告因为在相应的帧中没有向 Python 字节码转移控制权。

int PyTrace_EXCEPTION

当一个异常被引发时传给 Py_tracefunc 函数的 what 形参的值。 在处理完任何字节码之后将附带 what 的值调用回调函数,在此之后该异常将会被设置在正在执行的帧中。 这样做的效果是当异常传播导致 Python 栈展开时,被调用的回调函数将随异常传播返回到每个帧。 只有跟踪函数才会接收到这些事件;性能分析器并不需要它们。

int PyTrace_LINE

当一个行编号事件被报告时传给 Py_tracefunc 函数 (但不会传给性能分析函数) 的 what 形参的值。它可以通过将 f_trace_lines 设为 0 在某个帧中被禁用。

int PyTrace_RETURN

当一个调用即将返回时传给 Py_tracefunc 函数的 what 形参的值。

int PyTrace_C_CALL

当一个 C 函数即将被调用时传给 Py_tracefunc 函数的 what 形参的值。

int PyTrace_C_EXCEPTION

当一个 C 函数引发异常时传给 Py_tracefunc 函数的 what 形参的值。

int PyTrace_C_RETURN

当一个 C 函数返回时传给 Py_tracefunc 函数的 what 形参的值。

int PyTrace_OPCODE

当一个新操作码即将被执行时传给 Py_tracefunc 函数 (但不会传给性能分析函数) 的 what 形参的值。 在默认情况下此事件不会被发送:它必须通过在某个帧上将 f_trace_opcodes 设为 1 来显式地请求。

void PyEval_SetProfile(Py_tracefunc func, PyObject *obj)

将性能分析器函数设为 func。 obj 形参将作为第一个形参传给该函数,它可以是任意 Python 对象或为 NULL。 如果性能分析函数需要维护状态,则为每个线程的 obj 使用不同的值将提供一个方便而线程安全的存储位置。这个性能分析函数将针对除 PyTrace_LINE PyTrace_OPCODE 和 PyTrace_EXCEPTION 以外的所有被监控事件进行调用。

另请参阅 sys.setprofile() 函数。

调用方必须有已附加的线程状态 attached thread state。

void PyEval_SetProfileAllThreads(Py_tracefunc func, PyObject *obj)

类似于 PyEval_SetProfile() 但会在属于当前解释器的所有在运行线程中设置性能分析函数而不是仅在当前线程上设置。

调用方必须有已附加的线程状态 attached thread state。

与 PyEval_SetProfile() 一样,该函数会忽略任何被引发的异常同时在所有线程中设置性能分析函数。

在 3.12 版本加入.

void PyEval_SetTrace(Py_tracefunc func, PyObject *obj)

将跟踪函数设为 func。这类似于 PyEval_SetProfile(),区别在于跟踪函数会接收行编号事件和操作码级事件,但不会接收与被调用的 C 函数对象相关的任何事件。使用 PyEval_SetTrace() 注册的任何跟踪函数将不会接收 PyTrace_C_CALL、PyTrace_C_EXCEPTION 或 PyTrace_C_RETURN 作为 what 形参的值。

另请参阅 sys.settrace() 函数。

调用方必须有已附加的线程状态 attached thread state。

void PyEval_SetTraceAllThreads(Py_tracefunc func, PyObject *obj)

类似于 PyEval_SetTrace() 但会在属于当前解释器的所有在运行线程中设置跟踪函数而不是仅在当前线程上设置。

调用方必须有已附加的线程状态 attached thread state。

与 PyEval_SetTrace() 一样,该函数会忽略任何被引发的异常同时在所有线程中设置跟踪函数。

在 3.12 版本加入.

引用追踪

在 3.13 版本加入.

typedef int (*PyRefTracer)(PyObject*, int event, void *data)

使用 PyRefTracer_SetTracer() 注册的追踪函数的类型。第一个形参是刚创建(当 event 被设为 PyRefTracer_CREATE 时)或将销毁(当 event 被设为 PyRefTracer_DESTROY 时)的 Python 对象。 data 参数是当 PyRefTracer_SetTracer() 被调用时所提供的不透明指针。

如果注册了一个新的跟踪函数以替换当前函数,则调用跟踪函数时,对象将被设置为 NULL,event 将被设置为 PyRefTracer_TRACKER_REMOVED。这一操作将在新函数注册之前立即执行。

在 3.13 版本加入.

int PyRefTracer_CREATE

当一个 Python 对象被创建时传给 PyRefTracer 函数的 event 形参。

int PyRefTracer_DESTROY

当一个 Python 对象被销毁时传给 PyRefTracer 函数的 event 形参。

int PyRefTracer_TRACKER_REMOVED

当当前追踪器即将被新追踪器替换时,event 参数在 PyRefTracer 函数中的取值。

在 3.14 版本加入.

int PyRefTracer_SetTracer(PyRefTracer tracer, void *data)

注册一个引用追踪器函数。当创建新的 Python 对象或准备销毁某个对象时,将调用该函数。如果提供 data,则它必须是一个 opaque 指针,并在调用追踪器函数时提供该指针。成功时返回 0;发生错误时设置异常并返回 -1。

请注意,追踪函数**不得**在调用内部或外部创建 Python 对象,否则该调用将具有重入性。追踪器也**不得**清除任何已存在的异常或设置异常。每当调用追踪函数时,thread state 都会处于激活状态。

当调用此函数时必须有一个 attached thread state。

如果已经注册了另一个追踪函数,则将在新函数注册之前,将 event 设置为 PyRefTracer_TRACKER_REMOVED 并调用旧函数。

在 3.13 版本加入.

PyRefTracer PyRefTracer_GetTracer(void **data)

获取已注册的引用追踪函数以及当 PyRefTracer_SetTracer() 被调用时所注册的不透明数据指针的值。 如果未注册任何追踪器则此函数将返回 NULL 并将 data 指针设为 NULL。

当调用此函数时必须有一个 attached thread state。

在 3.13 版本加入.

性能统计

PYSTATS_MAX_UOP_ID

CPython 为其分配性能统计计数器的大型微操作标识符。仅可在配置为 --enable-pystats 的构建版本中使用。

该常量仅供内部使用,对扩展模块没有用途。

自 3.15.2 版起已处于 Soft deprecated 状态.