mirror of https://github.com/python/cpython
GH-103082: Clean up the sys.monitoring docs (GH-110532)
This commit is contained in:
parent
94495d0387
commit
1991694117
|
@ -1,14 +1,16 @@
|
|||
:mod:`sys.monitoring` --- Execution event monitoring
|
||||
====================================================
|
||||
|
||||
.. module:: sys.monitoring
|
||||
:synopsis: Access and control event monitoring
|
||||
.. module:: sys.monitoring
|
||||
:synopsis: Access and control event monitoring
|
||||
|
||||
.. versionadded:: 3.12
|
||||
|
||||
-----------------
|
||||
|
||||
.. note::
|
||||
|
||||
``sys.monitoring`` is a namespace within the ``sys`` module,
|
||||
:mod:`sys.monitoring` is a namespace within the :mod:`sys` module,
|
||||
not an independent module, so there is no need to
|
||||
``import sys.monitoring``, simply ``import sys`` and then use
|
||||
``sys.monitoring``.
|
||||
|
@ -18,45 +20,45 @@ This namespace provides access to the functions and constants necessary to
|
|||
activate and control event monitoring.
|
||||
|
||||
As programs execute, events occur that might be of interest to tools that
|
||||
monitor execution. The :mod:`!sys.monitoring` namespace provides means to
|
||||
monitor execution. The :mod:`sys.monitoring` namespace provides means to
|
||||
receive callbacks when events of interest occur.
|
||||
|
||||
The monitoring API consists of three components:
|
||||
|
||||
* Tool identifiers
|
||||
* Events
|
||||
* Callbacks
|
||||
* `Tool identifiers`_
|
||||
* `Events`_
|
||||
* :ref:`Callbacks <callbacks>`
|
||||
|
||||
Tool identifiers
|
||||
----------------
|
||||
|
||||
A tool identifier is an integer and associated name.
|
||||
A tool identifier is an integer and the associated name.
|
||||
Tool identifiers are used to discourage tools from interfering with each
|
||||
other and to allow multiple tools to operate at the same time.
|
||||
Currently tools are completely independent and cannot be used to
|
||||
monitor each other. This restriction may be lifted in the future.
|
||||
|
||||
Before registering or activating events, a tool should choose an identifier.
|
||||
Identifiers are integers in the range 0 to 5.
|
||||
Identifiers are integers in the range 0 to 5 inclusive.
|
||||
|
||||
Registering and using tools
|
||||
'''''''''''''''''''''''''''
|
||||
|
||||
.. function:: use_tool_id(id: int, name: str) -> None
|
||||
|
||||
Must be called before ``id`` can be used.
|
||||
``id`` must be in the range 0 to 5 inclusive.
|
||||
Raises a ``ValueError`` if ``id`` is in use.
|
||||
Must be called before *id* can be used.
|
||||
*id* must be in the range 0 to 5 inclusive.
|
||||
Raises a :exc:`ValueError` if *id* is in use.
|
||||
|
||||
.. function:: free_tool_id(id: int) -> None
|
||||
|
||||
Should be called once a tool no longer requires ``id``.
|
||||
Should be called once a tool no longer requires *id*.
|
||||
|
||||
.. function:: get_tool(id: int) -> str | None
|
||||
|
||||
Returns the name of the tool if ``id`` is in use,
|
||||
Returns the name of the tool if *id* is in use,
|
||||
otherwise it returns ``None``.
|
||||
``id`` must be in the range 0 to 5 inclusive.
|
||||
*id* must be in the range 0 to 5 inclusive.
|
||||
|
||||
All IDs are treated the same by the VM with regard to events, but the
|
||||
following IDs are pre-defined to make co-operation of tools easier::
|
||||
|
@ -75,48 +77,89 @@ Events
|
|||
|
||||
The following events are supported:
|
||||
|
||||
BRANCH
|
||||
A conditional branch is taken (or not).
|
||||
CALL
|
||||
A call in Python code (event occurs before the call).
|
||||
C_RAISE
|
||||
Exception raised from any callable, except Python functions (event occurs after the exit).
|
||||
C_RETURN
|
||||
Return from any callable, except Python functions (event occurs after the return).
|
||||
EXCEPTION_HANDLED
|
||||
An exception is handled.
|
||||
INSTRUCTION
|
||||
A VM instruction is about to be executed.
|
||||
JUMP
|
||||
An unconditional jump in the control flow graph is made.
|
||||
LINE
|
||||
An instruction is about to be executed that has a different line number from the preceding instruction.
|
||||
PY_RESUME
|
||||
Resumption of a Python function (for generator and coroutine functions), except for throw() calls.
|
||||
PY_RETURN
|
||||
Return from a Python function (occurs immediately before the return, the callee's frame will be on the stack).
|
||||
PY_START
|
||||
Start of a Python function (occurs immediately after the call, the callee's frame will be on the stack)
|
||||
PY_THROW
|
||||
A Python function is resumed by a throw() call.
|
||||
PY_UNWIND
|
||||
Exit from a Python function during exception unwinding.
|
||||
PY_YIELD
|
||||
Yield from a Python function (occurs immediately before the yield, the callee's frame will be on the stack).
|
||||
RAISE
|
||||
An exception is raised, except those that cause a ``STOP_ITERATION`` event.
|
||||
RERAISE
|
||||
An exception is re-raised, for example at the end of a ``finally`` block.
|
||||
STOP_ITERATION
|
||||
An artificial ``StopIteration`` is raised; see `the STOP_ITERATION event`_.
|
||||
.. monitoring-event:: BRANCH
|
||||
|
||||
A conditional branch is taken (or not).
|
||||
|
||||
.. monitoring-event:: CALL
|
||||
|
||||
A call in Python code (event occurs before the call).
|
||||
|
||||
.. monitoring-event:: C_RAISE
|
||||
|
||||
An exception raised from any callable, except for Python functions (event occurs after the exit).
|
||||
|
||||
.. monitoring-event:: C_RETURN
|
||||
|
||||
Return from any callable, except for Python functions (event occurs after the return).
|
||||
|
||||
.. monitoring-event:: EXCEPTION_HANDLED
|
||||
|
||||
An exception is handled.
|
||||
|
||||
.. monitoring-event:: INSTRUCTION
|
||||
|
||||
A VM instruction is about to be executed.
|
||||
|
||||
.. monitoring-event:: JUMP
|
||||
|
||||
An unconditional jump in the control flow graph is made.
|
||||
|
||||
.. monitoring-event:: LINE
|
||||
|
||||
An instruction is about to be executed that has a different line number from the preceding instruction.
|
||||
|
||||
.. monitoring-event:: PY_RESUME
|
||||
|
||||
Resumption of a Python function (for generator and coroutine functions), except for ``throw()`` calls.
|
||||
|
||||
.. monitoring-event:: PY_RETURN
|
||||
|
||||
Return from a Python function (occurs immediately before the return, the callee's frame will be on the stack).
|
||||
|
||||
.. monitoring-event:: PY_START
|
||||
|
||||
Start of a Python function (occurs immediately after the call, the callee's frame will be on the stack)
|
||||
|
||||
.. monitoring-event:: PY_THROW
|
||||
|
||||
A Python function is resumed by a ``throw()`` call.
|
||||
|
||||
.. monitoring-event:: PY_UNWIND
|
||||
|
||||
Exit from a Python function during exception unwinding.
|
||||
|
||||
.. monitoring-event:: PY_YIELD
|
||||
|
||||
Yield from a Python function (occurs immediately before the yield, the callee's frame will be on the stack).
|
||||
|
||||
.. monitoring-event:: RAISE
|
||||
|
||||
An exception is raised, except those that cause a :monitoring-event:`STOP_ITERATION` event.
|
||||
|
||||
.. monitoring-event:: RERAISE
|
||||
|
||||
An exception is re-raised, for example at the end of a :keyword:`finally` block.
|
||||
|
||||
.. monitoring-event:: STOP_ITERATION
|
||||
|
||||
An artificial :exc:`StopIteration` is raised; see `the STOP_ITERATION event`_.
|
||||
|
||||
|
||||
More events may be added in the future.
|
||||
|
||||
These events are attributes of the :mod:`!sys.monitoring.events` namespace.
|
||||
Each event is represented as a power-of-2 integer constant.
|
||||
To define a set of events, simply bitwise or the individual events together.
|
||||
For example, to specify both ``PY_RETURN`` and ``PY_START`` events, use the
|
||||
expression ``PY_RETURN | PY_START``.
|
||||
For example, to specify both :monitoring-event:`PY_RETURN` and :monitoring-event:`PY_START`
|
||||
events, use the expression ``PY_RETURN | PY_START``.
|
||||
|
||||
.. monitoring-event:: NO_EVENTS
|
||||
|
||||
An alias for ``0`` so users can do explict comparisions like::
|
||||
|
||||
if get_events(DEBUGGER_ID) == NO_EVENTS:
|
||||
...
|
||||
|
||||
Events are divided into three groups:
|
||||
|
||||
|
@ -127,16 +170,16 @@ Local events are associated with normal execution of the program and happen
|
|||
at clearly defined locations. All local events can be disabled.
|
||||
The local events are:
|
||||
|
||||
* PY_START
|
||||
* PY_RESUME
|
||||
* PY_RETURN
|
||||
* PY_YIELD
|
||||
* CALL
|
||||
* LINE
|
||||
* INSTRUCTION
|
||||
* JUMP
|
||||
* BRANCH
|
||||
* STOP_ITERATION
|
||||
* :monitoring-event:`PY_START`
|
||||
* :monitoring-event:`PY_RESUME`
|
||||
* :monitoring-event:`PY_RETURN`
|
||||
* :monitoring-event:`PY_YIELD`
|
||||
* :monitoring-event:`CALL`
|
||||
* :monitoring-event:`LINE`
|
||||
* :monitoring-event:`INSTRUCTION`
|
||||
* :monitoring-event:`JUMP`
|
||||
* :monitoring-event:`BRANCH`
|
||||
* :monitoring-event:`STOP_ITERATION`
|
||||
|
||||
Ancillary events
|
||||
''''''''''''''''
|
||||
|
@ -144,12 +187,13 @@ Ancillary events
|
|||
Ancillary events can be monitored like other events, but are controlled
|
||||
by another event:
|
||||
|
||||
* C_RAISE
|
||||
* C_RETURN
|
||||
* :monitoring-event:`C_RAISE`
|
||||
* :monitoring-event:`C_RETURN`
|
||||
|
||||
The ``C_RETURN`` and ``C_RAISE`` events are controlled by the ``CALL``
|
||||
event. ``C_RETURN`` and ``C_RAISE`` events will only be seen if the
|
||||
corresponding ``CALL`` event is being monitored.
|
||||
The :monitoring-event:`C_RETURN` and :monitoring-event:`C_RAISE` events
|
||||
are controlled by the :monitoring-event:`CALL` event.
|
||||
:monitoring-event:`C_RETURN` and :monitoring-event:`C_RAISE` events will only be seen if the
|
||||
corresponding :monitoring-event:`CALL` event is being monitored.
|
||||
|
||||
Other events
|
||||
''''''''''''
|
||||
|
@ -159,30 +203,31 @@ program and cannot be individually disabled.
|
|||
|
||||
The other events that can be monitored are:
|
||||
|
||||
* PY_THROW
|
||||
* PY_UNWIND
|
||||
* RAISE
|
||||
* EXCEPTION_HANDLED
|
||||
* :monitoring-event:`PY_THROW`
|
||||
* :monitoring-event:`PY_UNWIND`
|
||||
* :monitoring-event:`RAISE`
|
||||
* :monitoring-event:`EXCEPTION_HANDLED`
|
||||
|
||||
|
||||
The STOP_ITERATION event
|
||||
''''''''''''''''''''''''
|
||||
|
||||
:pep:`PEP 380 <380#use-of-stopiteration-to-return-values>`
|
||||
specifies that a ``StopIteration`` exception is raised when returning a value
|
||||
specifies that a :exc:`StopIteration` exception is raised when returning a value
|
||||
from a generator or coroutine. However, this is a very inefficient way to
|
||||
return a value, so some Python implementations, notably CPython 3.12+, do not
|
||||
raise an exception unless it would be visible to other code.
|
||||
|
||||
To allow tools to monitor for real exceptions without slowing down generators
|
||||
and coroutines, the ``STOP_ITERATION`` event is provided.
|
||||
``STOP_ITERATION`` can be locally disabled, unlike ``RAISE``.
|
||||
and coroutines, the :monitoring-event:`STOP_ITERATION` event is provided.
|
||||
:monitoring-event:`STOP_ITERATION` can be locally disabled, unlike :monitoring-event:`RAISE`.
|
||||
|
||||
|
||||
Turning events on and off
|
||||
-------------------------
|
||||
|
||||
In order to monitor an event, it must be turned on and a callback registered.
|
||||
In order to monitor an event, it must be turned on and a corresponding callback
|
||||
must be registered.
|
||||
Events can be turned on or off by setting the events either globally or
|
||||
for a particular code object.
|
||||
|
||||
|
@ -198,8 +243,8 @@ Events can be controlled globally by modifying the set of events being monitored
|
|||
|
||||
.. function:: set_events(tool_id: int, event_set: int)
|
||||
|
||||
Activates all events which are set in ``event_set``.
|
||||
Raises a ``ValueError`` if ``tool_id`` is not in use.
|
||||
Activates all events which are set in *event_set*.
|
||||
Raises a :exc:`ValueError` if *tool_id* is not in use.
|
||||
|
||||
No events are active by default.
|
||||
|
||||
|
@ -210,12 +255,12 @@ Events can also be controlled on a per code object basis.
|
|||
|
||||
.. function:: get_local_events(tool_id: int, code: CodeType) -> int
|
||||
|
||||
Returns all the local events for ``code``
|
||||
Returns all the local events for *code*
|
||||
|
||||
.. function:: set_local_events(tool_id: int, code: CodeType, event_set: int)
|
||||
|
||||
Activates all the local events for ``code`` which are set in ``event_set``.
|
||||
Raises a ``ValueError`` if ``tool_id`` is not in use.
|
||||
Activates all the local events for *code* which are set in *event_set*.
|
||||
Raises a :exc:`ValueError` if *tool_id* is not in use.
|
||||
|
||||
Local events add to global events, but do not mask them.
|
||||
In other words, all global events will trigger for a code object,
|
||||
|
@ -225,8 +270,13 @@ regardless of the local events.
|
|||
Disabling events
|
||||
''''''''''''''''
|
||||
|
||||
.. data:: DISABLE
|
||||
|
||||
A special value that can be returned from a callback function to disable
|
||||
events for the current code location.
|
||||
|
||||
Local events can be disabled for a specific code location by returning
|
||||
``sys.monitoring.DISABLE`` from a callback function. This does not change
|
||||
:data:`sys.monitoring.DISABLE` from a callback function. This does not change
|
||||
which events are set, or any other code locations for the same event.
|
||||
|
||||
Disabling events for specific locations is very important for high
|
||||
|
@ -235,6 +285,8 @@ debugger with no overhead if the debugger disables all monitoring
|
|||
except for a few breakpoints.
|
||||
|
||||
|
||||
.. _callbacks:
|
||||
|
||||
Registering callback functions
|
||||
------------------------------
|
||||
|
||||
|
@ -242,11 +294,11 @@ To register a callable for events call
|
|||
|
||||
.. function:: register_callback(tool_id: int, event: int, func: Callable | None) -> Callable | None
|
||||
|
||||
Registers the callable ``func`` for the ``event`` with the given ``tool_id``
|
||||
Registers the callable *func* for the *event* with the given *tool_id*
|
||||
|
||||
If another callback was registered for the given ``tool_id`` and ``event``,
|
||||
If another callback was registered for the given *tool_id* and *event*,
|
||||
it is unregistered and returned.
|
||||
Otherwise ``register_callback`` returns ``None``.
|
||||
Otherwise :func:`register_callback` returns ``None``.
|
||||
|
||||
|
||||
Functions can be unregistered by calling
|
||||
|
@ -254,47 +306,51 @@ Functions can be unregistered by calling
|
|||
|
||||
Callback functions can be registered and unregistered at any time.
|
||||
|
||||
Registering or unregistering a callback function will generate a ``sys.audit`` event.
|
||||
Registering or unregistering a callback function will generate a :func:`sys.audit` event.
|
||||
|
||||
|
||||
Callback function arguments
|
||||
'''''''''''''''''''''''''''
|
||||
|
||||
.. data:: MISSING
|
||||
|
||||
A special value that is passed to a callback function to indicate
|
||||
that there are no arguments to the call.
|
||||
|
||||
When an active event occurs, the registered callback function is called.
|
||||
Different events will provide the callback function with different arguments, as follows:
|
||||
|
||||
* ``PY_START`` and ``PY_RESUME``::
|
||||
* :monitoring-event:`PY_START` and :monitoring-event:`PY_RESUME`::
|
||||
|
||||
func(code: CodeType, instruction_offset: int) -> DISABLE | Any
|
||||
|
||||
* ``PY_RETURN`` and ``PY_YIELD``:
|
||||
* :monitoring-event:`PY_RETURN` and :monitoring-event:`PY_YIELD`::
|
||||
|
||||
``func(code: CodeType, instruction_offset: int, retval: object) -> DISABLE | Any``
|
||||
func(code: CodeType, instruction_offset: int, retval: object) -> DISABLE | Any
|
||||
|
||||
* ``CALL``, ``C_RAISE`` and ``C_RETURN``:
|
||||
* :monitoring-event:`CALL`, :monitoring-event:`C_RAISE` and :monitoring-event:`C_RETURN`::
|
||||
|
||||
``func(code: CodeType, instruction_offset: int, callable: object, arg0: object | MISSING) -> DISABLE | Any``
|
||||
func(code: CodeType, instruction_offset: int, callable: object, arg0: object | MISSING) -> DISABLE | Any
|
||||
|
||||
If there are no arguments, ``arg0`` is set to ``MISSING``.
|
||||
If there are no arguments, *arg0* is set to :data:`sys.monitoring.MISSING`.
|
||||
|
||||
* ``RAISE``, ``RERAISE``, ``EXCEPTION_HANDLED``, ``PY_UNWIND``, ``PY_THROW`` and ``STOP_ITERATION``:
|
||||
* :monitoring-event:`RAISE`, :monitoring-event:`RERAISE`, :monitoring-event:`EXCEPTION_HANDLED`,
|
||||
:monitoring-event:`PY_UNWIND`, :monitoring-event:`PY_THROW` and :monitoring-event:`STOP_ITERATION`::
|
||||
|
||||
``func(code: CodeType, instruction_offset: int, exception: BaseException) -> DISABLE | Any``
|
||||
func(code: CodeType, instruction_offset: int, exception: BaseException) -> DISABLE | Any
|
||||
|
||||
* ``LINE``:
|
||||
* :monitoring-event:`LINE`::
|
||||
|
||||
``func(code: CodeType, line_number: int) -> DISABLE | Any``
|
||||
func(code: CodeType, line_number: int) -> DISABLE | Any
|
||||
|
||||
* ``BRANCH`` and ``JUMP``:
|
||||
* :monitoring-event:`BRANCH` and :monitoring-event:`JUMP`::
|
||||
|
||||
``func(code: CodeType, instruction_offset: int, destination_offset: int) -> DISABLE | Any``
|
||||
func(code: CodeType, instruction_offset: int, destination_offset: int) -> DISABLE | Any
|
||||
|
||||
Note that the ``destination_offset`` is where the code will next execute.
|
||||
Note that the *destination_offset* is where the code will next execute.
|
||||
For an untaken branch this will be the offset of the instruction following
|
||||
the branch.
|
||||
|
||||
* ``INSTRUCTION``:
|
||||
|
||||
``func(code: CodeType, instruction_offset: int) -> DISABLE | Any``
|
||||
|
||||
* :monitoring-event:`INSTRUCTION`::
|
||||
|
||||
func(code: CodeType, instruction_offset: int) -> DISABLE | Any
|
||||
|
|
|
@ -607,6 +607,13 @@ def parse_pdb_command(env, sig, signode):
|
|||
return fullname
|
||||
|
||||
|
||||
def parse_monitoring_event(env, sig, signode):
|
||||
"""Transform a monitoring event signature into RST nodes."""
|
||||
signode += addnodes.desc_addname('sys.monitoring.events.', 'sys.monitoring.events.')
|
||||
signode += addnodes.desc_name(sig, sig)
|
||||
return sig
|
||||
|
||||
|
||||
def process_audit_events(app, doctree, fromdocname):
|
||||
for node in doctree.traverse(audit_event_list):
|
||||
break
|
||||
|
@ -707,6 +714,7 @@ def setup(app):
|
|||
app.add_builder(PydocTopicsBuilder)
|
||||
app.add_object_type('opcode', 'opcode', '%s (opcode)', parse_opcode_signature)
|
||||
app.add_object_type('pdbcommand', 'pdbcmd', '%s (pdb command)', parse_pdb_command)
|
||||
app.add_object_type('monitoring-event', 'monitoring-event', '%s (monitoring event)', parse_monitoring_event)
|
||||
app.add_directive_to_domain('py', 'decorator', PyDecoratorFunction)
|
||||
app.add_directive_to_domain('py', 'decoratormethod', PyDecoratorMethod)
|
||||
app.add_directive_to_domain('py', 'coroutinefunction', PyCoroutineFunction)
|
||||
|
|
Loading…
Reference in New Issue