> **Источник:** https://python-all.ru/3.13/library/sys.monitoring.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

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

Добавлено в версии 3.12.

---

> **Примечание**
>
> `sys.monitoring` – это пространство имён в модуле [`sys`](https://python-all.ru/3.13/library/sys.html#module-sys), не независимый модуль, и попытка `import sys.monitoring` приведёт к ошибке [`ModuleNotFoundError`](https://python-all.ru/3.13/library/exceptions.html#ModuleNotFoundError). Вместо этого достаточно `import sys` и затем использовать `sys.monitoring`.

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

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

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

- [Идентификаторы инструментов](https://python-all.ru/3.13/library/sys.monitoring.html#tool-identifiers)
- [События](https://python-all.ru/3.13/library/sys.monitoring.html#events)
- [Колбэки](https://python-all.ru/3.13/library/sys.monitoring.html#callbacks)

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

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

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

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

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

Должен быть вызван до того, как *tool\_id* можно будет использовать. *tool\_id* должен находиться в диапазоне от 0 до 5 включительно. Вызывает исключение [`ValueError`](https://python-all.ru/3.13/library/exceptions.html#ValueError), если *tool\_id* уже используется.

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

Должна вызываться, когда инструмент больше не требует *tool\_id*.

> **Примечание**
>
> [`free_tool_id()`](https://python-all.ru/3.13/library/sys.monitoring.html#sys.monitoring.free_tool_id) не отключает глобальные или локальные события, связанные с *tool\_id*, а также не отменяет регистрацию каких-либо функций обратного вызова. Эта функция предназначена только для уведомления виртуальной машины о том, что конкретный *tool\_id* больше не используется.

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

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

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

```python
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`

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

#### `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`

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

#### `sys.monitoring.events.RAISE`

Исключение возбуждается, за исключением тех, которые приводят к событию [`STOP_ITERATION`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-STOP_ITERATION).

#### `sys.monitoring.events.RERAISE`

Исключение возбуждается повторно, например, в конце блока [`finally`](https://python-all.ru/3.13/reference/compound_stmts.html#finally).

#### `sys.monitoring.events.STOP_ITERATION`

Возбуждается искусственное [`StopIteration`](https://python-all.ru/3.13/library/exceptions.html#StopIteration); см. [событие STOP\_ITERATION](https://python-all.ru/3.13/library/sys.monitoring.html#the-stop-iteration-event).

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

Эти события являются атрибутами пространства имён `sys.monitoring.events`. Каждое событие представлено целочисленной константой, являющейся степенью двойки. Чтобы определить набор событий, достаточно объединить отдельные события побитовым ИЛИ. Например, чтобы указать оба события [`PY_RETURN`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-PY_RETURN) и [`PY_START`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-PY_START), используйте выражение `PY_RETURN | PY_START`.

#### `sys.monitoring.events.NO_EVENTS`

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

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

События разделены на три группы:

### Локальные события

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

- [`PY_START`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-PY_START)
- [`PY_RESUME`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-PY_RESUME)
- [`PY_RETURN`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-PY_RETURN)
- [`PY_YIELD`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-PY_YIELD)
- [`CALL`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-CALL)
- [`LINE`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-LINE)
- [`INSTRUCTION`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-INSTRUCTION)
- [`JUMP`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-JUMP)
- [`BRANCH`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-BRANCH)
- [`STOP_ITERATION`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-STOP_ITERATION)

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

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

- [`C_RAISE`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-C_RAISE)
- [`C_RETURN`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-C_RETURN)

События [`C_RETURN`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-C_RETURN) и [`C_RAISE`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-C_RAISE) управляются событием [`CALL`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-CALL). События `C_RETURN` и `C_RAISE` будут видны только при отслеживании соответствующего события `CALL`.

### Прочие события

Прочие события не обязательно привязаны к конкретному месту в программе и не могут быть отключены по отдельности через [`DISABLE`](https://python-all.ru/3.13/library/sys.monitoring.html#sys.monitoring.DISABLE).

Прочие события, которые можно отслеживать:

- [`PY_THROW`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-PY_THROW)
- [`PY_UNWIND`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-PY_UNWIND)
- [`RAISE`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-RAISE)
- [`EXCEPTION_HANDLED`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-EXCEPTION_HANDLED)

### Событие STOP\_ITERATION

[**PEP 380**](https://python-all.ru/3.13/library/sys.monitoring.html) указывает, что при возврате значения из генератора или корутины возбуждается исключение [`StopIteration`](https://python-all.ru/3.13/library/exceptions.html#StopIteration). Однако это очень неэффективный способ возврата значения, поэтому некоторые реализации Python, в частности CPython 3.12+, не возбуждают исключение, если оно не будет видно другому коду.

Чтобы инструменты могли отслеживать реальные исключения, не замедляя работу генераторов и корутин, предоставляется событие [`STOP_ITERATION`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-STOP_ITERATION). `STOP_ITERATION` можно отключать локально, в отличие от [`RAISE`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-RAISE).

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

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

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

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

#### `sys.monitoring.get_events(tool_id: int, /) → int`

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

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

Активирует все события, установленные в *event\_set*. Возбуждает [`ValueError`](https://python-all.ru/3.13/library/exceptions.html#ValueError), если *tool\_id* не используется.

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

### События для каждого объекта кода

События также можно контролировать для каждого объекта кода. Функции, определённые ниже и принимающие [`types.CodeType`](https://python-all.ru/3.13/library/types.html#types.CodeType), должны быть готовы принять объект-имитацию от функций, не определённых на Python (см. [Monitoring C API](https://python-all.ru/3.13/c-api/monitoring.html#c-api-monitoring)).

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

Возвращает все [локальные события](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-local) для *code*

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

Активирует все [локальные события](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-local) для *code*, установленные в *event\_set*. Возбуждает [`ValueError`](https://python-all.ru/3.13/library/exceptions.html#ValueError), если *tool\_id* не используется.

Локальные события добавляются к глобальным, но не скрывают их. Иными словами, все глобальные события срабатывают для объекта кода независимо от локальных событий.

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

#### `sys.monitoring.DISABLE`

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

[Локальные события](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-local) можно отключить для конкретного места в коде, вернув [`sys.monitoring.DISABLE`](https://python-all.ru/3.13/library/sys.monitoring.html#sys.monitoring.DISABLE) из функции обратного вызова. Это не меняет, какие события установлены, и не затрагивает другие места в коде для того же события.

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

Если [`DISABLE`](https://python-all.ru/3.13/library/sys.monitoring.html#sys.monitoring.DISABLE) возвращается функцией обратного вызова для [глобального события](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-global), то [`ValueError`](https://python-all.ru/3.13/library/exceptions.html#ValueError) будет возбуждено интерпретатором в неопределённом месте (то есть traceback не будет предоставлен).

#### `sys.monitoring.restart_events() → None`

Включить все события, которые были отключены вызовом [`sys.monitoring.DISABLE`](https://python-all.ru/3.13/library/sys.monitoring.html#sys.monitoring.DISABLE) для всех инструментов.

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

Чтобы зарегистрировать вызываемый объект для событий, вызовите

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

Регистрирует вызываемый объект *func* для события *event* с заданным *tool\_id*

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

Вызывает [событие аудита](https://python-all.ru/3.13/library/sys.html#auditing) `sys.monitoring.register_callback` с аргументом `func`.

Функции можно отменить, вызвав `sys.monitoring.register_callback(tool_id, event, None)`.

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

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

#### `sys.monitoring.MISSING`

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

Когда происходит активное событие, вызывается зарегистрированный колбэк. Разные события передают колбэку различные аргументы, как показано ниже:

- [`PY_START`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-PY_START) и [`PY_RESUME`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-PY_RESUME):

  ```python
  func(code: CodeType, instruction_offset: int) -> DISABLE | Any
  ```
- [`PY_RETURN`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-PY_RETURN) и [`PY_YIELD`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-PY_YIELD):

  ```python
  func(code: CodeType, instruction_offset: int, retval: object) -> DISABLE | Any
  ```
- [`CALL`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-CALL), [`C_RAISE`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-C_RAISE) и [`C_RETURN`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-C_RETURN):

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

  Если аргументы отсутствуют, *arg0* устанавливается в [`sys.monitoring.MISSING`](https://python-all.ru/3.13/library/sys.monitoring.html#sys.monitoring.MISSING).
- [`RAISE`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-RAISE), [`RERAISE`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-RERAISE), [`EXCEPTION_HANDLED`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-EXCEPTION_HANDLED), [`PY_UNWIND`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-PY_UNWIND), [`PY_THROW`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-PY_THROW) и [`STOP_ITERATION`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-STOP_ITERATION):

  ```python
  func(code: CodeType, instruction_offset: int, exception: BaseException) -> DISABLE | Any
  ```
- [`LINE`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-LINE):

  ```python
  func(code: CodeType, line_number: int) -> DISABLE | Any
  ```
- [`BRANCH`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-BRANCH) и [`JUMP`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-JUMP):

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

  Обратите внимание, что *destination\_offset* – это смещение, по которому код будет выполняться далее. Для невыбранной ветки это будет смещение инструкции, следующей за веткой.
- [`INSTRUCTION`](https://python-all.ru/3.13/library/sys.monitoring.html#monitoring-event-INSTRUCTION):

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