sys.monitoring
— Мониторинг событий выполнения¶
Added in version 3.12.
Примечание
sys.monitoring
- это пространство имен внутри модуля sys
, а не самостоятельный модуль, поэтому нет необходимости в import sys.monitoring
, достаточно import 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 ¶
Вызывается, когда инструмент больше не требует tool_id.
Примечание
free_tool_id()
не отключит глобальные или локальные события, связанные с tool_id, и не снимет с регистрации какие-либо функции обратного вызова. Эта функция предназначена только для уведомления виртуальной машины о том, что конкретный tool_id больше не используется.
- sys.monitoring.get_tool(tool_id: int, /) str | None ¶
Возвращает имя инструмента, если tool_id используется, в противном случае возвращает
None
. tool_id должен находиться в диапазоне от 0 до 5 включительно.
Все идентификаторы обрабатываются VM одинаково в отношении событий, но для облегчения совместной работы инструментов предварительно определены следующие идентификаторы:
sys.monitoring.DEBUGGER_ID = 0
sys.monitoring.COVERAGE_ID = 1
sys.monitoring.PROFILER_ID = 2
sys.monitoring.OPTIMIZER_ID = 5
События¶
Поддерживаются следующие события:
- sys.monitoring.events.BRANCH¶
Выполняется (или не выполняется) условная ветвь.
- 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¶
Выход из функции Python во время разворачивания исключения.
- sys.monitoring.events.PY_YIELD¶
Выход из функции Python (происходит непосредственно перед выходом, фрейм вызывающего будет находиться в стеке).
- sys.monitoring.events.RAISE¶
Возникает исключение, за исключением тех, которые вызывают событие
STOP_ITERATION
.
- sys.monitoring.events.STOP_ITERATION¶
Поднимается искусственный
StopIteration
; см. the STOP_ITERATION event.
В будущем могут быть добавлены новые мероприятия.
Эти события являются атрибутами пространства имен sys.monitoring.events
. Каждое событие представлено в виде целочисленной константы мощностью 2. Чтобы определить набор событий, просто выполните побитовую комбинацию отдельных событий. Например, чтобы указать оба события PY_RETURN
и PY_START
, используйте выражение PY_RETURN | PY_START
.
- sys.monitoring.events.NO_EVENTS¶
Псевдоним для
0
, чтобы пользователи могли выполнять явные сравнения, например:if get_events(DEBUGGER_ID) == NO_EVENTS: ...
События разделены на три группы:
Местные события¶
Локальные события связаны с нормальным выполнением программы и происходят в четко определенных местах. Все локальные события можно отключить. К локальным событиям относятся:
Вспомогательные мероприятия¶
Вспомогательные события можно отслеживать, как и другие события, но они контролируются другим событием:
События C_RETURN
и C_RAISE
контролируются событием CALL
. События C_RETURN
и C_RAISE
будут видны, только если отслеживается соответствующее событие CALL
.
Другие события¶
Другие события не обязательно привязаны к конкретному месту в программе и не могут быть индивидуально отключены.
Другими событиями, которые можно отслеживать, являются:
Событие STOP_ITERATION¶
PEP 380 указывает, что при возврате значения из генератора или корутины возбуждается исключение StopIteration
. Однако это очень неэффективный способ возврата значения, поэтому некоторые реализации Python, в частности CPython 3.12+, не поднимают исключение, если это не будет заметно для другого кода.
Чтобы инструменты могли отслеживать реальные исключения без замедления работы генераторов и корутинов, предусмотрено событие STOP_ITERATION
. STOP_ITERATION
может быть локально отключен, в отличие от RAISE
.
Включение и выключение событий¶
Для того чтобы отслеживать событие, его необходимо включить и зарегистрировать соответствующий обратный вызов. События можно включить или выключить, задав их либо глобально, либо для конкретного объекта кода.
Глобальная настройка событий¶
Событиями можно управлять глобально, изменяя набор отслеживаемых событий.
- 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 (см. API Monitorong C).
- sys.monitoring.get_local_events(tool_id: int, code: CodeType, /) int ¶
Возвращает все локальные события для code.
- sys.monitoring.set_local_events(tool_id: int, code: CodeType, event_set: int, /) None ¶
Активирует все локальные события для code, заданные в event_set. Вызывает ошибку
ValueError
, если tool_id не используется.
Локальные события добавляются к глобальным, но не маскируют их. Другими словами, все глобальные события будут срабатывать для объекта кода, независимо от локальных событий.
Отключение событий¶
- sys.monitoring.DISABLE¶
Специальное значение, которое может быть возвращено из функции обратного вызова для отключения событий для текущего местоположения кода.
Локальные события могут быть отключены для определенного места кода путем возврата sys.monitoring.DISABLE
из функции обратного вызова. При этом не изменяется, какие события устанавливаются, и не изменяются другие кодовые места для того же события.
Отключение событий для определенных мест очень важно для высокопроизводительного мониторинга. Например, программа может быть запущена под отладчиком без каких-либо накладных расходов, если отладчик отключит весь мониторинг, кроме нескольких точек останова.
- sys.monitoring.restart_events() None ¶
Включите все события, которые были отключены с помощью
sys.monitoring.DISABLE
для всех инструментов.
Регистрация функций обратного вызова¶
Чтобы зарегистрировать вызываемый элемент для событий, вызовите
- sys.monitoring.register_callback(tool_id: int, event: int, func: Callable | None, /) Callable | None ¶
Регистрирует вызываемую функцию для события с заданным tool_id.
Если для данного tool_id и event был зарегистрирован другой обратный вызов, то он снимается с регистрации и возвращается. В противном случае
register_callback()
возвращаетсяNone
.
Функции можно снять с регистрации, вызвав sys.monitoring.register_callback(tool_id, event, None)
.
Функции обратного вызова могут быть зарегистрированы и сняты с регистрации в любое время.
Регистрация или снятие с регистрации функции обратного вызова приведет к появлению события sys.audit()
.
Аргументы функции обратного вызова¶
- sys.monitoring.MISSING¶
Специальное значение, которое передается функции обратного вызова, чтобы указать на отсутствие аргументов в вызове.
Когда происходит активное событие, вызывается зарегистрированная функция обратного вызова. Различные события предоставляют функции обратного вызова различные аргументы, как показано ниже:
-
func(code: CodeType, instruction_offset: int) -> DISABLE | Any
-
func(code: CodeType, instruction_offset: int, retval: object) -> DISABLE | Any
-
func(code: CodeType, instruction_offset: int, callable: object, arg0: object | MISSING) -> DISABLE | Any
Если аргументов нет, arg0 устанавливается в
sys.monitoring.MISSING
. RAISE
,RERAISE
,EXCEPTION_HANDLED
,PY_UNWIND
,PY_THROW
иSTOP_ITERATION
:func(code: CodeType, instruction_offset: int, exception: BaseException) -> DISABLE | Any
LINE
:func(code: CodeType, line_number: int) -> DISABLE | Any
-
func(code: CodeType, instruction_offset: int, destination_offset: int) -> DISABLE | Any
Обратите внимание, что смещение_назначения - это место, где код будет выполняться в следующий раз. Для непринятого ответвления это будет смещение инструкции, следующей за ответвлением.
-
func(code: CodeType, instruction_offset: int) -> DISABLE | Any