Python

sys.monitoring — 실행 이벤트 모니터링

Added in version 3.12.


참고

sys.monitoring 은 독립적인 모듈이 아니라 sys 모듈 내의 네임스페이스입니다. 따라서 import sys.monitoring 을 실행하면 ModuleNotFoundError 가 발생합니다. 대신, 단순히 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 사이의 범위 내에 있어야 합니다. tool_id 가 이미 사용 중이면 ValueError 를 발생시킵니다.

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

tool_id 와 연관된 모든 이벤트 및 콜백 함수를 등록 해제합니다.

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

도구가 더 이상 tool_id 를 필요로 하지 않을 때 호출해야 합니다. tool_id 를 해제하기 전에 clear_tool_id() 를 호출합니다.

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

tool_id 가 사용 중이면 해당 도구의 이름을 반환하고, 그렇지 않으면 None 을 반환합니다. tool_id 는 0에서 5 사이의 범위 내에 있어야 합니다.

VM은 이벤트와 관련하여 모든 ID를 동일하게 처리하지만, 도구 간의 협력을 원활하게 하기 위해 다음 ID들이 미리 정의되어 있습니다:

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

이벤트

다음 이벤트가 지원됩니다:

sys.monitoring.events.BRANCH_LEFT

조건 분기가 왼쪽으로 이동합니다.

“왼쪽”과 “오른쪽” 분기를 어떻게 표현할지는 도구의 결정에 달려 있습니다. 어떤 분기가 “왼쪽”이고 어떤 것이 “오른쪽”인지 보장할 수는 없지만, 프로그램이 실행되는 동안은 일관되게 유지됩니다.

sys.monitoring.events.BRANCH_RIGHT

조건 분리가 오른쪽으로 이동합니다.

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

throw() 호출을 제외한 Python 함수의 재개(제너레이터 및 코루틴 함수용).

sys.monitoring.events.PY_RETURN

Python 함수의 반환(반환 직전에 발생하며, 호출자의 프레임이 스택에 남아 있음).

sys.monitoring.events.PY_START

Python 함수의 시작(호출 직후에 발생하며, 호출자의 프레임이 스택에 있음)

sys.monitoring.events.PY_THROW

throw() 호출에 의해 Python 함수가 재개됨.

sys.monitoring.events.PY_UNWIND

예외 언와인딩(unwinding) 중에 Python 함수를 종료함. 여기에는 함수 내부에서 직접 발생한 예외와 전파를 허용하는 예외가 모두 포함됩니다.

sys.monitoring.events.PY_YIELD

Python 함수의 Yield(yield 직전에 발생하며, 호출자의 프레임이 스택에 남아 있음).

sys.monitoring.events.RAISE

STOP_ITERATION 이벤트를 발생시키는 예외를 제외하고 발생한 예외.

sys.monitoring.events.RERAISE

예외가 다시 던져짐(예를 들어 finally 블록 끝에서).

sys.monitoring.events.STOP_ITERATION

인위적인 StopIteration 이 발생함; the STOP_ITERATION event 를 참조하십시오.

향후 더 많은 이벤트가 추가될 수 있습니다.

이 이벤트들은 sys.monitoring.events 네임스페이스의 속성입니다. 각 이벤트는 2의 거듭제곱인 정수 상수로 표현됩니다. 여러 이벤트를 정의하려면 개별 이벤트를 비트 단위 OR 연산으로 결합하십시오. 예를 들어, PY_RETURNPY_START 를 모두 지정하려면 PY_RETURN | PY_START 표현식을 사용하십시오.

sys.monitoring.events.NO_EVENTS

사용자가 다음과 같이 명시적인 비교를 수행할 수 있도록 하는 0 의 별칭입니다:

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

이 이벤트를 설정하면 모든 이벤트가 비활성화됩니다.

로컬 이벤트

로컬 이벤트는 프로그램의 일반적인 실행과 관련이 있으며 명확하게 정의된 위치에서 발생합니다. 모든 로컬 이벤트는 장소별로 비활성화할 수 있습니다. 로컬 이벤트들은 다음과 같습니다.

더 이상 사용되지 않는(Deprecated) 이벤트

  • BRANCH

BRANCH 이벤트는 3.14 버전부터 사용이 권장되지 않습니다(deprecated). BRANCH_LEFTBRANCH_RIGHT 이벤트를 사용하면 각각 독립적으로 비활성화할 수 있어 성능이 훨씬 더 좋습니다.

부수적인 이벤트

부수적인 이벤트는 다른 이벤트와 마찬가지로 모니터링할 수 있지만, 다른 이벤트에 의해 제어됩니다:

C_RETURNC_RAISE 이벤트는 CALL 이벤트에 의해 제어됩니다. C_RETURNC_RAISE 이벤트는 해당 CALL 이벤트가 모니터링되는 경우에만 보입니다.

기타 이벤트

기타 이벤트는 반드시 프로그램의 특정 위치와 연결되어 있지 않으며 장소별로 개별적으로 비활성화할 수 없습니다.

모니터링 가능한 다른 이벤트들은 다음과 같습니다:

버전 3.15에서 변경: 이제 다른 이벤트들을 코드 객체별로 켜거나 끌 수 있습니다. 콜백에서 DISABLE 을 반환하면 해당 코드 객체 전체에 대해 해당 이벤트가 비활성화됩니다(현재 도구에 한함).

STOP_ITERATION 이벤트

PEP 380 는 제너레이터나 코루틴에서 값을 반환할 때 StopIteration 예외가 발생함을 규정합니다. 그러나 이는 값을 반환하는 매우 비효율적인 방식이므로, CPython 3.12+를 포함한 일부 Python 구현체에서는 다른 코드에 노출되지 않는 한 예외를 발생시키지 않습니다.

제너레이터와 코루틴의 속도를 저하시키지 않으면서 실제 예외를 모니터링할 수 있도록 STOP_ITERATION 이벤트가 제공됩니다. STOP_ITERATION 은 로컬에서 비활성화할 수 있습니다.

STOP_ITERATION 이벤트와 StopIteration 예외에 대한 RAISE 이벤트는 서로 동등하며, 이벤트를 생성할 때 상호 대체 가능한 것으로 취급됩니다. 구현체는 성능상의 이유로 STOP_ITERATION 을 선호하지만, StopIteration 을 포함하는 RAISE 이벤트를 생성할 수도 있습니다.

이벤트 켜기 및 끄기

이벤트를 모니터링하려면 이벤트가 켜져 있어야 하며 그에 해당하는 콜백이 등록되어야 합니다. 이벤트는 전역적으로 또는 특정 코드 객체에 대해 설정함으로써 켤 수도 있고 끌 수도 있습니다. 이벤트가 전역 및 로컬 모두에서 켜져 있더라도 한 번만 트리거됩니다.

이벤트를 전역으로 설정하기

모니터링되는 이벤트 세트를 수정하여 이벤트를 전역적으로 제어할 수 있습니다.

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

활성화된 모든 이벤트를 나타내는 int 를 반환합니다.

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

event_set 에 설정된 모든 이벤트를 활성화합니다. tool_id 가 사용 중이 아니면 ValueError 를 발생시킵니다.

기본적으로 활성화된 이벤트는 없습니다.

코드 객체별 이벤트

이벤트는 코드 객체 단위로도 제어할 수 있습니다. types.CodeType 을 인자로 받는 아래에 정의된 함수들은 파이썬에서 정의되지 않은 기능으로부터 전달되는 유사한 객체를 수용할 준비가 되어 있어야 합니다(참조: 모니터링 C API).

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

code 에 대한 모든 local events 을 반환합니다.

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

event_set 에 설정된 code 의 모든 local events 을 활성화합니다. tool_id 가 사용 중이 아니면 ValueError 를 발생시킵니다.

이벤트 비활성화

sys.monitoring.DISABLE

현재 코드 위치에 대한 이벤트를 비활성화하기 위해 콜백 함수에서 반환할 수 있는 특별한 값입니다.

콜백 함수에서 sys.monitoring.DISABLE 을 반환하여 특정 코드 위치에 대한 Local events 를 비활성화할 수 있습니다. 이는 설정된 이벤트 종류나 동일한 이벤트의 다른 코드 위치에는 영향을 주지 않습니다.

콜백 함수에서 sys.monitoring.DISABLE 을 반환하여 코드 객체 단위로 Other events 를 비활성화할 수 있습니다. 이는 현재 도구에 대해 해당 코드 객체 전체에 대한 이벤트를 비활성화합니다.

특정 위치에 대한 이벤트를 비활성화하는 것은 고성능 모니터링에서 매우 중요합니다. 예를 들어, 디버거가 몇 개의 중단점(breakpoint)을 제외한 모든 모니터링을 비활성화하면 프로그램은 오버헤드 없이 디버거 아래에서 실행될 수 있습니다.

sys.monitoring.restart_events() None

모든 도구에 대해 sys.monitoring.DISABLE 으로 비활성화된 모든 이벤트를 활성화합니다.

콜백 함수 등록

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

주어진 tool_idevent 에 대해 호출 가능한 func 를 등록합니다.

주어진 tool_idevent 에 다른 콜백이 등록되어 있다면, 해당 콜백을 등록 해제하고 반환합니다. 그렇지 않으면 register_callback()None 을 반환합니다.

인자 func 를 사용하여 auditing event sys.monitoring.register_callback 을 발생시킵니다.

sys.monitoring.register_callback(tool_id, event, None) 을 호출하여 함수 등록을 취소할 수 있습니다.

콜백 함수는 언제든지 등록하거나 해제할 수 있습니다.

이벤트가 전역 및 로컬 모두에서 켜져 있더라도 콜백은 단 한 번만 호출됩니다. 따라서 사용자의 코드에 의해 전역 및 로컬 이벤트가 모두 켜질 수 있는 경우, 콜백은 두 경우 모두를 처리할 수 있도록 작성되어야 합니다.

콜백 함수 인자

sys.monitoring.MISSING

호출에 대한 인자가 없음을 나타내기 위해 콜백 함수에 전달되는 특별한 값입니다.

활성화된 이벤트가 발생하면 등록된 콜백 함수가 호출됩니다. DISABLE 이 아닌 객체를 반환하는 콜백 함수는 아무런 영향을 주지 않습니다. 서로 다른 이벤트는 다음과 같이 콜백 함수에 서로 다른 인자를 제공합니다.

  • PY_STARTPY_RESUME:

    func(code: CodeType, instruction_offset: int) -> object
    
  • PY_RETURNPY_YIELD:

    func(code: CodeType, instruction_offset: int, retval: object) -> object
    
  • CALL, C_RAISEC_RETURN (arg0 은 특히 MISSING 일 수 있음):

    func(code: CodeType, instruction_offset: int, callable: object, arg0: object) -> object
    

    code 는 호출이 수행되는 코드 객체를 나타내며, callable 은 호출될 예정인(따라서 이벤트를 발생시키는) 객체입니다. 인자가 없는 경우 arg0sys.monitoring.MISSING 으로 설정됩니다.

    인스턴스 메서드의 경우, callable 은 클래스에서 찾은 함수 객체이며 arg0 은 인스턴스(즉, 메서드의 self 인자)로 설정됩니다.

  • RAISE, RERAISE, EXCEPTION_HANDLED, PY_UNWIND, PY_THROWSTOP_ITERATION:

    func(code: CodeType, instruction_offset: int, exception: BaseException) -> object
    
  • LINE:

    func(code: CodeType, line_number: int) -> object
    
  • BRANCH_LEFT, BRANCH_RIGHTJUMP:

    func(code: CodeType, instruction_offset: int, destination_offset: int) -> object
    

    destination_offset 은 코드가 다음에 실행될 위치입니다.

  • INSTRUCTION:

    func(code: CodeType, instruction_offset: int) -> object