sys.monitoring — Мониторинг событий выполнения

Dodane w wersji 3.12.


Informacja

sys.monitoring — это пространство имен внутри модуля sys, а не независимый модуль, поэтому нет необходимости импортировать sys.monitoring, просто импортируйте sys, а затем используйте sys.monitoring.

Это пространство имен обеспечивает доступ к функциям и константам, необходимым для активации и управления мониторингом событий.

Во время выполнения программ происходят события, которые могут представлять интерес для инструментов, отслеживающих выполнение. Пространство имен sys.monitoring предоставляет средства для получения обратных вызовов при возникновении интересующих событий.

API мониторинга состоит из трех компонентов:

Идентификаторы инструментов

Идентификатор инструмента представляет собой целое число и связанное с ним имя. Идентификаторы инструментов используются для предотвращения взаимодействия инструментов друг с другом и для обеспечения одновременной работы нескольких инструментов. На данный момент инструменты полностью независимы и не могут использоваться для мониторинга друг друга. В будущем это ограничение может быть снято.

Прежде чем регистрировать или активировать события, инструмент должен выбрать идентификатор. Идентификаторы представляют собой целые числа в диапазоне от 0 до 5 включительно.

Регистрация и использование инструментов

sys.monitoring.use_tool_id(tool_id: int, name: str, /) None

Должен быть вызван перед использованием tool_id. tool_id должен находиться в диапазоне от 0 до 5 включительно. Вызывает ValueError, если tool_id используется.

sys.monitoring.free_tool_id(tool_id: int, /) None

Should be called once a tool no longer requires tool_id.

Informacja

free_tool_id() will not disable global or local events associated with tool_id, nor will it unregister any callback functions. This function is only intended to be used to notify the VM that the particular tool_id is no longer in use.

sys.monitoring.get_tool(tool_id: int, /) str | None

Возвращает имя инструмента, если tool_id используется, в противном случае возвращается None. tool_id должен находиться в диапазоне от 0 до 5 включительно.

Все идентификаторы обрабатываются виртуальной машиной одинаково в отношении событий, но следующие идентификаторы предопределены для упрощения взаимодействия инструментов:

sys.monitoring.DEBUGGER_ID = 0
sys.monitoring.COVERAGE_ID = 1
sys.monitoring.PROFILER_ID = 2
sys.monitoring.OPTIMIZER_ID = 5

События

Поддерживаются следующие события:

sys.monitoring.events.BRANCH

A conditional branch is taken (or not).

sys.monitoring.events.CALL

Вызов в коде Python (событие происходит перед вызовом).

sys.monitoring.events.C_RAISE

Исключение, возникающее из любого вызываемого объекта, кроме функций Python (событие возникает после выхода).

sys.monitoring.events.C_RETURN

Возврат из любого вызываемого объекта, кроме функций Python (событие происходит после возврата).

sys.monitoring.events.EXCEPTION_HANDLED

Исключение обрабатывается.

sys.monitoring.events.INSTRUCTION

Инструкция VM скоро будет выполнена.

sys.monitoring.events.JUMP

Производится безусловный переход в графе потока управления.

sys.monitoring.events.LINE

Скоро будет выполнена инструкция, номер строки которой отличается от номера предыдущей инструкции.

sys.monitoring.events.PY_RESUME

Возобновление работы функции Python (для функций генератора и сопрограммы), за исключением вызовов throw().

sys.monitoring.events.PY_RETURN

Возврат из функции Python (происходит непосредственно перед возвратом, кадр вызываемого объекта будет находиться в стеке).

sys.monitoring.events.PY_START

Запуск функции Python (происходит сразу после вызова, кадр вызываемого объекта будет в стеке)

sys.monitoring.events.PY_THROW

Функция Python возобновляется вызовом throw().

sys.monitoring.events.PY_UNWIND

Exit from a Python function during exception unwinding.

sys.monitoring.events.PY_YIELD

Выход из функции Python (происходит непосредственно перед выходом, кадр вызываемого объекта будет в стеке).

sys.monitoring.events.RAISE

Вызывается исключение, за исключением тех, которые вызывают событие STOP_ITERATION.

sys.monitoring.events.RERAISE

Исключение возникает повторно, например, в конце блока finally.

sys.monitoring.events.STOP_ITERATION

Вызывается искусственный StopIteration; см. событие STOP_ITERATION.

В будущем могут быть добавлены и другие мероприятия.

Esses eventos são atributos do espaço de nomes sys.monitoring.events. Cada evento é representado como uma constante de potência de 2 inteiros. Para definir um conjunto de eventos, basta aplicar OU (OR) bit a bit nos eventos individuais juntos. Por exemplo, para especificar os eventos PY_RETURN e PY_START, use a expressão PY_RETURN | PY_START.

sys.monitoring.events.NO_EVENTS

Псевдоним для 0, чтобы пользователи могли выполнять явные сравнения, например:

if get_events(DEBUGGER_ID) == NO_EVENTS:
    ...

Events are divided into three groups:

Местные события

Локальные события связаны с обычным выполнением программы и происходят в четко определенных местах. Все локальные события можно отключить. Местные мероприятия:

Вспомогательные мероприятия

Вспомогательные события можно отслеживать, как и другие события, но они контролируются другим событием:

События C_RETURN и C_RAISE управляются событием CALL. События C_RETURN и C_RAISE будут видны только в том случае, если отслеживается соответствующее событие CALL.

Другие события

Другие события не обязательно привязаны к определенному месту в программе и не могут быть отключены индивидуально.

Другие события, которые можно отслеживать:

Событие STOP_ITERATION

PEP 380 указывает, что исключение StopIteration возникает при возврате значения из генератора или сопрограммы. Однако это очень неэффективный способ вернуть значение, поэтому некоторые реализации Python, особенно CPython 3.12+, не вызывают исключение, если оно не будет видно другому коду.

Чтобы инструменты могли отслеживать реальные исключения, не замедляя работу генераторов и сопрограмм, предусмотрено событие STOP_ITERATION. STOP_ITERATION можно отключить локально, в отличие от RAISE.

Включение и выключение событий

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.

Глобальная настройка событий

Событиями можно управлять глобально, изменяя набор отслеживаемых событий.

sys.monitoring.get_events(tool_id: int, /) int

Возвращает int, представляющий все активные события.

sys.monitoring.set_events(tool_id: int, event_set: int, /) None

Активирует все события, заданные в event_set. Вызывает ValueError, если tool_id не используется.

По умолчанию ни одно событие не является активным.

События объекта кода

Событиями также можно управлять для каждого объекта кода. Определенные ниже функции, которые принимают types.CodeType, должны быть готовы принять похожий объект из функций, которые не определены в Python (см. Monitoring C API).

sys.monitoring.get_local_events(tool_id: int, code: CodeType, /) int

Возвращает все локальные события для кода

sys.monitoring.set_local_events(tool_id: int, code: CodeType, event_set: int, /) None

Активирует все локальные события для code, которые установлены в event_set. Вызывает ValueError, если tool_id не используется.

Local events add to global events, but do not mask them. In other words, all global events will trigger for a code object, regardless of the local events.

Отключение событий

sys.monitoring.DISABLE

Специальное значение, которое может быть возвращено функцией обратного вызова для отключения событий для текущего местоположения кода.

Локальные события можно отключить для определенного места кода, вернув sys.monitoring.DISABLE из функции обратного вызова. Это не влияет на то, какие события установлены или какие-либо другие места кода для того же события.

Отключение событий для определенных мест очень важно для обеспечения высокой производительности мониторинга. Например, программу можно запустить под отладчиком без дополнительных затрат, если отладчик отключит весь мониторинг, за исключением нескольких точек останова.

sys.monitoring.restart_events() None

Включите все события, которые были отключены с помощью sys.monitoring.DISABLE для всех инструментов.

Регистрация функций обратного вызова

To register a callable for events call

sys.monitoring.register_callback(tool_id: int, event: int, func: Callable | None, /) Callable | None

Регистрирует вызываемую функцию для события с заданным tool_id.

Если для заданных tool_id и event был зарегистрирован другой обратный вызов, он отменяется и возвращается. В противном случае register_callback() возвращает None.

Raises an auditing event sys.monitoring.register_callback with argument func.

Регистрация функций может быть отменена путем вызова sys.monitoring.register_callback(tool_id, event, None).

Функции обратного вызова можно зарегистрировать и отменить регистрацию в любое время.

Аргументы функции обратного вызова

sys.monitoring.MISSING

Специальное значение, которое передается в функцию обратного вызова, чтобы указать, что у вызова нет аргументов.

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 и PY_RESUME:

    func(code: CodeType, instruction_offset: int) -> DISABLE | Any
    
  • PY_RETURN и PY_YIELD:

    func(code: CodeType, instruction_offset: int, retval: object) -> DISABLE | Any
    
  • CALL, C_RAISE and C_RETURN:

    func(code: CodeType, instruction_offset: int, callable: object, arg0: object | MISSING) -> DISABLE | Any
    

    If there are no arguments, arg0 is set to sys.monitoring.MISSING.

  • RAISE, RERAISE, EXCEPTION_HANDLED, PY_UNWIND, PY_THROW и :monitoring-event: STOP_ITERATION:

    func(code: CodeType, instruction_offset: int, exception: BaseException) -> DISABLE | Any
    
  • LINE:

    func(code: CodeType, line_number: int) -> DISABLE | Any
    
  • BRANCH and JUMP:

    func(code: CodeType, instruction_offset: int, destination_offset: int) -> DISABLE | Any
    

    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