# Profiling and tracing

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

  The value of the what parameter to a `Py_tracefunc` function when an exception has been raised. The callback function is called with this value for what when after any bytecode is processed after which the exception becomes set within the frame being executed. The effect of this is that as exception propagation causes the Python stack to unwind, the callback is called upon return to each frame as the exception propagates. Only trace functions receive these events; they are not needed by the profiler.

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()` 一样，该函数会忽略任何被引发的异常同时在所有线程中设置性能分析函数。

Added in version 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()` 一样，该函数会忽略任何被引发的异常同时在所有线程中设置跟踪函数。

Added in version 3.12.

# 引用追踪

Added in version 3.13.

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

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

  If a new tracing function is registered replacing the current one, a call to the trace function will be made with the object set to NULL and event set to `PyRefTracer_TRACKER_REMOVED`. This will happen just before the new function is registered.

Added in version 3.13.

int PyRefTracer_CREATE

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

int PyRefTracer_DESTROY

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

int PyRefTracer_TRACKER_REMOVED

  The value for the event parameter to `PyRefTracer` functions when the current tracer is about to be replaced by a new one.

  Added in version 3.14.

int PyRefTracer_SetTracer(PyRefTracer tracer, void *data)

  Register a reference tracer function. The function will be called when a new Python object has been created or when an object is going to be destroyed. If data is provided it must be an opaque pointer that will be provided when the tracer function is called. Return `0` on success. Set an exception and return `-1` on error.

  Note that tracer functions must not create Python objects inside or otherwise the call will be re-entrant. The tracer also must not clear any existing exception or set an exception. A thread state will be active every time the tracer function is called.

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

  If another tracer function was already registered, the old function will be called with event set to `PyRefTracer_TRACKER_REMOVED` just before the new function is registered.

Added in version 3.13.

PyRefTracer PyRefTracer_GetTracer(void **data)

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

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

Added in version 3.13.