# `sys.monitoring` — Monitoramento de eventos de execução

Adicionado na versão 3.12.

Nota

`sys.monitoring` é um espaço de nomes dentro do módulo `sys`, não um módulo independente, então não há necessidade de importá-lo com `import sys.monitoring`, bastando usar `import sys` e então usar `sys.monitoring`.

Esse espaço de nomes fornece acesso às funções e constantes necessárias para ativar e controlar o monitoramento de eventos.

À medida que os programas são executados, ocorrem eventos que podem ser de interesse para as ferramentas que monitoram a execução. O espaço de nomes `sys.monitoring` fornece meios para receber retornos de chamada quando ocorrem eventos de interesse.

A API de monitoramento consiste em três componentes:

- Identificadores de ferramenta

- Eventos

- Funções de retorno de chamadas

## Identificadores de ferramenta

Um identificador de ferramenta é um número inteiro e o nome associado. Os identificadores de ferramenta são usados para evitar que as ferramentas interfiram umas nas outras e para permitir que várias ferramentas operem ao mesmo tempo. Atualmente, as ferramentas são totalmente independentes e não podem ser usadas para monitorar umas às outras. Essa restrição poderá ser suspensa no futuro.

Antes de registrar ou ativar eventos, uma ferramenta deve escolher um identificador. Os identificadores são números inteiros no intervalo de 0 a 5, inclusive.

### Registro e uso de ferramentas

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

  Deve ser chamado antes que tool_id possa ser usado. tool_id deve estar no intervalo de 0 a 5, inclusive. Levanta um `ValueError` se tool_id estiver em uso.

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

  Deve ser chamado quando uma ferramenta não precisar mais do endereço tool_id.

Nota

`free_tool_id()` não desabilitará eventos globais ou locais associados a tool_id, nem cancelará o registro de qualquer função de retorno. Essa função deve ser usada apenas para notificar a VM de que o tool_id específico não está mais em uso.

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

  Retorna o nome da ferramenta se tool_id estiver em uso; caso contrário, retorna `None`. tool_id deve estar no intervalo de 0 a 5, inclusive.

Todas as IDs são tratadas da mesma forma pela VM com relação aos eventos, mas as seguintes IDs são predefinidas para facilitar a cooperação entre as ferramentas:

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

Não há obrigação de definir uma ID, nem há nada que impeça uma ferramenta de usar uma ID, mesmo que ela já esteja em uso. No entanto, as ferramentas são incentivadas a usar uma ID exclusiva e a respeitar as outras ferramentas.

## Eventos

Os seguintes eventos são suportados:

sys.monitoring.events.BRANCH

  Uma ramificação condicional é feita (ou não).

sys.monitoring.events.CALL

  Uma chamada no código Python (o evento ocorre antes da chamada).

sys.monitoring.events.C_RAISE

  Uma exceção levantada por qualquer chamável, exceto funções Python (o evento ocorre após a saída).

sys.monitoring.events.C_RETURN

  Retorno de qualquer chamável, exceto por funções Python (o evento ocorre após o retorno).

sys.monitoring.events.EXCEPTION_HANDLED

  Uma exceção é tratada.

sys.monitoring.events.INSTRUCTION

  Uma instrução VM está prestes a ser executada.

sys.monitoring.events.JUMP

  É feito um salto incondicional no gráfico do fluxo de controle.

sys.monitoring.events.LINE

  Está prestes a ser executada uma instrução que tem um número de linha diferente da instrução anterior.

sys.monitoring.events.PY_RESUME

  Retomada de uma função Python (para funções geradoras e de corrotina), exceto para chamadas `throw()`.

sys.monitoring.events.PY_RETURN

  Retorno de uma função Python (ocorre imediatamente antes do retorno, o quadro do receptor estará na pilha).

sys.monitoring.events.PY_START

  Início de uma função Python (ocorre imediatamente após a chamada, o quadro do receptor da chamada estará na pilha)

sys.monitoring.events.PY_THROW

  Uma função Python é retomada por uma chamada `throw()`.

sys.monitoring.events.PY_UNWIND

  Saída de uma função Python durante o desenrolar da exceção.

sys.monitoring.events.PY_YIELD

  Produz de uma função Python (ocorre imediatamente antes do yield, o quadro do receptor estará na pilha).

sys.monitoring.events.RAISE

  Uma exceção é levantada, exceto aquelas que causam um evento `STOP_ITERATION`.

sys.monitoring.events.RERAISE

  Uma exceção é levantada novamente, por exemplo, no final de um bloco `finally`.

sys.monitoring.events.STOP_ITERATION

  Uma exceção artificial `StopIteration` é levantada; consulte o evento STOP_ITERATION.

Mais eventos poderão ser adicionados no futuro.

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 usar o bit a bit ou os 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

  Um apelido para `0` para que os usuários possam fazer comparações explícitas como:

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

Os eventos são divididos em três grupos:

### Eventos locais

Os eventos locais estão associados à execução normal do programa e ocorrem em locais claramente definidos. Todos os eventos locais podem ser desativados. Os eventos locais são:

- `PY_START`

- `PY_RESUME`

- `PY_RETURN`

- `PY_YIELD`

- `CALL`

- `LINE`

- `INSTRUCTION`

- `JUMP`

- `BRANCH`

- `STOP_ITERATION`

### Eventos auxiliares

Os eventos auxiliares podem ser monitorados como outros eventos, mas são controlados por outro evento:

- `C_RAISE`

- `C_RETURN`

Os eventos `C_RETURN` e `C_RAISE` são controlados pelo evento `CALL`. Os eventos `C_RETURN` e `C_RAISE` só serão vistos se o evento `CALL` correspondente estiver sendo monitorado.

### Outros eventos

Outros eventos não estão necessariamente vinculados a um local específico no programa e não podem ser desativados individualmente.

Os outros eventos que podem ser monitorados são:

- `PY_THROW`

- `PY_UNWIND`

- `RAISE`

- `EXCEPTION_HANDLED`

### O evento STOP_ITERATION

PEP 380 especifica que uma exceção `StopIteration` é levantada ao retornar um valor de um gerador ou corrotina. No entanto, essa é uma maneira muito ineficiente de retornar um valor, portanto, algumas implementações do Python, especialmente o CPython 3.12+, não levantam uma exceção, a menos que ela seja visível para outro código.

Para permitir que as ferramentas monitorem exceções reais sem reduzir a velocidade dos geradores e das corrotinas, o evento `STOP_ITERATION` é fornecido. O `STOP_ITERATION` pode ser desativado localmente, ao contrário do `RAISE`.

## Ativação e desativação de eventos

Para monitorar um evento, ele deve ser ativado e uma função de retorno correspondente deve ser registrada. Os eventos podem ser ativados ou desativados definindo-os globalmente ou para um objeto código específico.

### Definir eventos globalmente

Os eventos podem ser controlados globalmente, modificando o conjunto de eventos que estão sendo monitorados.

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

  Retorna o endereço `int` que representa todos os eventos ativos.

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

  Ativa todos os eventos definidos em event_set. Levanta um `ValueError` se tool_id não estiver em uso.

Nenhum evento está ativo por padrão.

### Eventos por objeto código

Os eventos também podem ser controlados com base em cada objeto código.

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

  Retorna todos os eventos locais para code

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

  Ativa todos os eventos locais para code que estão definidos em event_set. Levanta a `ValueError` se tool_id não estiver em uso.

Os eventos locais são adicionados aos eventos globais, mas não os mascaram. Em outras palavras, todos os eventos globais serão acionados para um objeto código, independentemente dos eventos locais.

### Desativação de eventos

sys.monitoring.DISABLE

  Um valor especial que pode ser retornado de um função de retorno função para desativar eventos para o local do código atual.

Os eventos locais podem ser desativados para um local de código específico, retornando `sys.monitoring.DISABLE` de uma função de retorno de chamada. Isso não altera quais eventos são definidos ou quaisquer outros locais de código para o mesmo evento.

A desativação de eventos para locais específicos é muito importante para o monitoramento de alto desempenho. Por exemplo, um programa pode ser executado em um depurador sem sobrecarga se o depurador desativar todo o monitoramento, exceto alguns pontos de interrupção.

sys.monitoring.restart_events() → None

  Habilita todos os eventos que foram desabilitados por `sys.monitoring.DISABLE` para todas as ferramentas.

## Registro de funções de retorno de chamada

Para registrar um chamável para eventos, chame

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

  Registra o chamável func para o event com o tool_id fornecido

  Se outra função de retorno tiver sido registrada para o tool_id e o event fornecidos, ela será cancelada e retornada. Caso contrário, `register_callback()` retorna `None`.

As funções podem ser canceladas chamando `sys.monitoring.register_callback(tool_id, event, None)`.

As funções de retorno de chamada podem ser registradas e canceladas a qualquer momento.

O registro ou o cancelamento do registro de uma função de retorno de chamada gerará um evento `sys.audit()`.

### Argumentos da função de retorno de chamada

sys.monitoring.MISSING

  Um valor especial que é passado para uma função de retorno para indicar que não há argumento para a chamada.

Quando ocorre um evento ativo, a função de retorno de chamada registrada é chamada. Eventos diferentes fornecerão à função de retorno de chamada argumentos diferentes, como segue:

- `PY_START` e `PY_RESUME`:

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

- `PY_RETURN` e `PY_YIELD`:

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

- `CALL`, `C_RAISE` e `C_RETURN`:

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

  Se não houver argumentos, arg0 será definido como `sys.monitoring.MISSING`.

- `RAISE`, `RERAISE`, `EXCEPTION_HANDLED`, `PY_UNWIND`, `PY_THROW` e `STOP_ITERATION`:

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

- `LINE`:

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

- `BRANCH` e `JUMP`:

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

  Observe que destination_offset é onde o código será executado em seguida. Para uma ramificação não executada, esse será o deslocamento da instrução que segue a ramificação.

- `INSTRUCTION`:

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