• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1:mod:`!sys.monitoring` --- Execution event monitoring
2=====================================================
3
4.. module:: sys.monitoring
5   :synopsis: Access and control event monitoring
6
7.. versionadded:: 3.12
8
9-----------------
10
11.. note::
12
13    :mod:`sys.monitoring` is a namespace within the :mod:`sys` module,
14    not an independent module, so there is no need to
15    ``import sys.monitoring``, simply ``import sys`` and then use
16    ``sys.monitoring``.
17
18
19This namespace provides access to the functions and constants necessary to
20activate and control event monitoring.
21
22As programs execute, events occur that might be of interest to tools that
23monitor execution. The :mod:`sys.monitoring` namespace provides means to
24receive callbacks when events of interest occur.
25
26The monitoring API consists of three components:
27
28* `Tool identifiers`_
29* `Events`_
30* :ref:`Callbacks <callbacks>`
31
32Tool identifiers
33----------------
34
35A tool identifier is an integer and the associated name.
36Tool identifiers are used to discourage tools from interfering with each
37other and to allow multiple tools to operate at the same time.
38Currently tools are completely independent and cannot be used to
39monitor each other. This restriction may be lifted in the future.
40
41Before registering or activating events, a tool should choose an identifier.
42Identifiers are integers in the range 0 to 5 inclusive.
43
44Registering and using tools
45'''''''''''''''''''''''''''
46
47.. function:: use_tool_id(tool_id: int, name: str, /) -> None
48
49   Must be called before *tool_id* can be used.
50   *tool_id* must be in the range 0 to 5 inclusive.
51   Raises a :exc:`ValueError` if *tool_id* is in use.
52
53.. function:: free_tool_id(tool_id: int, /) -> None
54
55   Should be called once a tool no longer requires *tool_id*.
56
57.. note::
58
59   :func:`free_tool_id` will not disable global or local events associated
60   with *tool_id*, nor will it unregister any callback functions. This
61   function is only intended to be used to notify the VM that the
62   particular *tool_id* is no longer in use.
63
64.. function:: get_tool(tool_id: int, /) -> str | None
65
66   Returns the name of the tool if *tool_id* is in use,
67   otherwise it returns ``None``.
68   *tool_id* must be in the range 0 to 5 inclusive.
69
70All IDs are treated the same by the VM with regard to events, but the
71following IDs are pre-defined to make co-operation of tools easier::
72
73  sys.monitoring.DEBUGGER_ID = 0
74  sys.monitoring.COVERAGE_ID = 1
75  sys.monitoring.PROFILER_ID = 2
76  sys.monitoring.OPTIMIZER_ID = 5
77
78
79Events
80------
81
82The following events are supported:
83
84.. monitoring-event:: BRANCH
85
86   A conditional branch is taken (or not).
87
88.. monitoring-event:: CALL
89
90   A call in Python code (event occurs before the call).
91
92.. monitoring-event:: C_RAISE
93
94   An exception raised from any callable, except for Python functions (event occurs after the exit).
95
96.. monitoring-event:: C_RETURN
97
98   Return from any callable, except for Python functions (event occurs after the return).
99
100.. monitoring-event:: EXCEPTION_HANDLED
101
102   An exception is handled.
103
104.. monitoring-event:: INSTRUCTION
105
106   A VM instruction is about to be executed.
107
108.. monitoring-event:: JUMP
109
110   An unconditional jump in the control flow graph is made.
111
112.. monitoring-event:: LINE
113
114   An instruction is about to be executed that has a different line number from the preceding instruction.
115
116.. monitoring-event:: PY_RESUME
117
118   Resumption of a Python function (for generator and coroutine functions), except for ``throw()`` calls.
119
120.. monitoring-event:: PY_RETURN
121
122   Return from a Python function (occurs immediately before the return, the callee's frame will be on the stack).
123
124.. monitoring-event:: PY_START
125
126   Start of a Python function (occurs immediately after the call, the callee's frame will be on the stack)
127
128.. monitoring-event:: PY_THROW
129
130   A Python function is resumed by a ``throw()`` call.
131
132.. monitoring-event:: PY_UNWIND
133
134   Exit from a Python function during exception unwinding.
135
136.. monitoring-event:: PY_YIELD
137
138   Yield from a Python function (occurs immediately before the yield, the callee's frame will be on the stack).
139
140.. monitoring-event:: RAISE
141
142   An exception is raised, except those that cause a :monitoring-event:`STOP_ITERATION` event.
143
144.. monitoring-event:: RERAISE
145
146   An exception is re-raised, for example at the end of a :keyword:`finally` block.
147
148.. monitoring-event:: STOP_ITERATION
149
150   An artificial :exc:`StopIteration` is raised; see `the STOP_ITERATION event`_.
151
152
153More events may be added in the future.
154
155These events are attributes of the :mod:`!sys.monitoring.events` namespace.
156Each event is represented as a power-of-2 integer constant.
157To define a set of events, simply bitwise or the individual events together.
158For example, to specify both :monitoring-event:`PY_RETURN` and :monitoring-event:`PY_START`
159events, use the expression ``PY_RETURN | PY_START``.
160
161.. monitoring-event:: NO_EVENTS
162
163    An alias for ``0`` so users can do explicit comparisons like::
164
165      if get_events(DEBUGGER_ID) == NO_EVENTS:
166          ...
167
168Events are divided into three groups:
169
170Local events
171''''''''''''
172
173Local events are associated with normal execution of the program and happen
174at clearly defined locations. All local events can be disabled.
175The local events are:
176
177* :monitoring-event:`PY_START`
178* :monitoring-event:`PY_RESUME`
179* :monitoring-event:`PY_RETURN`
180* :monitoring-event:`PY_YIELD`
181* :monitoring-event:`CALL`
182* :monitoring-event:`LINE`
183* :monitoring-event:`INSTRUCTION`
184* :monitoring-event:`JUMP`
185* :monitoring-event:`BRANCH`
186* :monitoring-event:`STOP_ITERATION`
187
188Ancillary events
189''''''''''''''''
190
191Ancillary events can be monitored like other events, but are controlled
192by another event:
193
194* :monitoring-event:`C_RAISE`
195* :monitoring-event:`C_RETURN`
196
197The :monitoring-event:`C_RETURN` and :monitoring-event:`C_RAISE` events
198are controlled by the :monitoring-event:`CALL` event.
199:monitoring-event:`C_RETURN` and :monitoring-event:`C_RAISE` events will only be seen if the
200corresponding :monitoring-event:`CALL` event is being monitored.
201
202Other events
203''''''''''''
204
205Other events are not necessarily tied to a specific location in the
206program and cannot be individually disabled.
207
208The other events that can be monitored are:
209
210* :monitoring-event:`PY_THROW`
211* :monitoring-event:`PY_UNWIND`
212* :monitoring-event:`RAISE`
213* :monitoring-event:`EXCEPTION_HANDLED`
214
215
216The STOP_ITERATION event
217''''''''''''''''''''''''
218
219:pep:`PEP 380 <380#use-of-stopiteration-to-return-values>`
220specifies that a :exc:`StopIteration` exception is raised when returning a value
221from a generator or coroutine. However, this is a very inefficient way to
222return a value, so some Python implementations, notably CPython 3.12+, do not
223raise an exception unless it would be visible to other code.
224
225To allow tools to monitor for real exceptions without slowing down generators
226and coroutines, the :monitoring-event:`STOP_ITERATION` event is provided.
227:monitoring-event:`STOP_ITERATION` can be locally disabled, unlike :monitoring-event:`RAISE`.
228
229
230Turning events on and off
231-------------------------
232
233In order to monitor an event, it must be turned on and a corresponding callback
234must be registered.
235Events can be turned on or off by setting the events either globally or
236for a particular code object.
237
238
239Setting events globally
240'''''''''''''''''''''''
241
242Events can be controlled globally by modifying the set of events being monitored.
243
244.. function:: get_events(tool_id: int, /) -> int
245
246   Returns the ``int`` representing all the active events.
247
248.. function:: set_events(tool_id: int, event_set: int, /) -> None
249
250   Activates all events which are set in *event_set*.
251   Raises a :exc:`ValueError` if *tool_id* is not in use.
252
253No events are active by default.
254
255Per code object events
256''''''''''''''''''''''
257
258Events can also be controlled on a per code object basis. The functions
259defined below which accept a :class:`types.CodeType` should be prepared
260to accept a look-alike object from functions which are not defined
261in Python (see :ref:`c-api-monitoring`).
262
263.. function:: get_local_events(tool_id: int, code: CodeType, /) -> int
264
265   Returns all the local events for *code*
266
267.. function:: set_local_events(tool_id: int, code: CodeType, event_set: int, /) -> None
268
269   Activates all the local events for *code* which are set in *event_set*.
270   Raises a :exc:`ValueError` if *tool_id* is not in use.
271
272Local events add to global events, but do not mask them.
273In other words, all global events will trigger for a code object,
274regardless of the local events.
275
276
277Disabling events
278''''''''''''''''
279
280.. data:: DISABLE
281
282   A special value that can be returned from a callback function to disable
283   events for the current code location.
284
285Local events can be disabled for a specific code location by returning
286:data:`sys.monitoring.DISABLE` from a callback function. This does not change
287which events are set, or any other code locations for the same event.
288
289Disabling events for specific locations is very important for high
290performance monitoring. For example, a program can be run under a
291debugger with no overhead if the debugger disables all monitoring
292except for a few breakpoints.
293
294.. function:: restart_events() -> None
295
296   Enable all the events that were disabled by :data:`sys.monitoring.DISABLE`
297   for all tools.
298
299
300.. _callbacks:
301
302Registering callback functions
303------------------------------
304
305To register a callable for events call
306
307.. function:: register_callback(tool_id: int, event: int, func: Callable | None, /) -> Callable | None
308
309   Registers the callable *func* for the *event* with the given *tool_id*
310
311   If another callback was registered for the given *tool_id* and *event*,
312   it is unregistered and returned.
313   Otherwise :func:`register_callback` returns ``None``.
314
315
316Functions can be unregistered by calling
317``sys.monitoring.register_callback(tool_id, event, None)``.
318
319Callback functions can be registered and unregistered at any time.
320
321Registering or unregistering a callback function will generate a :func:`sys.audit` event.
322
323
324Callback function arguments
325'''''''''''''''''''''''''''
326
327.. data:: MISSING
328
329   A special value that is passed to a callback function to indicate
330   that there are no arguments to the call.
331
332When an active event occurs, the registered callback function is called.
333Different events will provide the callback function with different arguments, as follows:
334
335* :monitoring-event:`PY_START` and :monitoring-event:`PY_RESUME`::
336
337    func(code: CodeType, instruction_offset: int) -> DISABLE | Any
338
339* :monitoring-event:`PY_RETURN` and :monitoring-event:`PY_YIELD`::
340
341    func(code: CodeType, instruction_offset: int, retval: object) -> DISABLE | Any
342
343* :monitoring-event:`CALL`, :monitoring-event:`C_RAISE` and :monitoring-event:`C_RETURN`::
344
345    func(code: CodeType, instruction_offset: int, callable: object, arg0: object | MISSING) -> DISABLE | Any
346
347  If there are no arguments, *arg0* is set to :data:`sys.monitoring.MISSING`.
348
349* :monitoring-event:`RAISE`, :monitoring-event:`RERAISE`, :monitoring-event:`EXCEPTION_HANDLED`,
350  :monitoring-event:`PY_UNWIND`, :monitoring-event:`PY_THROW` and :monitoring-event:`STOP_ITERATION`::
351
352    func(code: CodeType, instruction_offset: int, exception: BaseException) -> DISABLE | Any
353
354* :monitoring-event:`LINE`::
355
356    func(code: CodeType, line_number: int) -> DISABLE | Any
357
358* :monitoring-event:`BRANCH` and :monitoring-event:`JUMP`::
359
360    func(code: CodeType, instruction_offset: int, destination_offset: int) -> DISABLE | Any
361
362  Note that the *destination_offset* is where the code will next execute.
363  For an untaken branch this will be the offset of the instruction following
364  the branch.
365
366* :monitoring-event:`INSTRUCTION`::
367
368    func(code: CodeType, instruction_offset: int) -> DISABLE | Any
369