sys.monitoring
— 執行事件監控¶
在 3.12 版本中新增。
註解
sys.monitoring
是 sys
模組中的一個名稱空間,而不是一個獨立的模組,因此無需 import sys.monitoring
,只需 import sys
然後使用 sys.monitoring
即可。
此名稱空間提供對啟用和控制事件監控所需的函式和常量的訪問。
當程式執行時,會發生一些工具可能感興趣的事件,這些工具可以監控執行。sys.monitoring
名稱空間提供了在發生感興趣的事件時接收回調的方法。
監控 API 由三個元件組成
工具識別符號¶
工具識別符號是一個整數和關聯的名稱。工具識別符號用於防止工具相互干擾,並允許多個工具同時執行。目前,工具是完全獨立的,不能用於互相監控。未來可能會取消此限制。
在註冊或啟用事件之前,工具應選擇一個識別符號。識別符號是 0 到 5 之間的整數(包括 0 和 5)。
註冊和使用工具¶
- sys.monitoring.use_tool_id(tool_id: int, name: str, /) None ¶
必須在 tool_id 可以使用之前呼叫。tool_id 必須在 0 到 5 的範圍內(包括 0 和 5)。如果 tool_id 正在使用,則會引發
ValueError
。
註解
free_tool_id()
不會停用與 tool_id 關聯的全域性或本地事件,也不會取消註冊任何回撥函式。此函式僅用於通知 VM,特定的 tool_id 不再使用。
- sys.monitoring.get_tool(tool_id: int, /) str | None ¶
如果 tool_id 正在使用,則返回工具的名稱,否則返回
None
。tool_id 必須在 0 到 5 的範圍內(包括 0 和 5)。
所有 ID 在 VM 中都以相同的方式處理事件,但以下 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¶
發生條件分支(被執行或不被執行)。
- 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¶
透過
throw()
呼叫恢復 Python 函式。
- sys.monitoring.events.PY_UNWIND¶
在異常展開期間從 Python 函式退出。
- sys.monitoring.events.PY_YIELD¶
從 Python 函式產生值(發生在 yield 之前,被呼叫者的幀將在堆疊上)。
- sys.monitoring.events.RAISE¶
引發異常,除了那些導致
STOP_ITERATION
事件的異常。
- sys.monitoring.events.STOP_ITERATION¶
引發一個人為的
StopIteration
異常;請參閱 STOP_ITERATION 事件。
未來可能會新增更多事件。
這些事件是 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
事件控制。 只有在監視相應的 CALL
事件時,才會看到 C_RETURN
和 C_RAISE
事件。
其他事件¶
其他事件不一定與程式中的特定位置相關聯,並且不能單獨停用。
可以監視的其他事件有
STOP_ITERATION 事件¶
PEP 380 指定,當從生成器或協程返回值時,會引發 StopIteration
異常。但是,這是一種非常低效的返回值方式,因此一些 Python 實現(特別是 CPython 3.12+)不會引發異常,除非它對其他程式碼可見。
為了允許工具在不減慢生成器和協程速度的情況下監視真實異常,提供了 STOP_ITERATION
事件。與 RAISE
不同,STOP_ITERATION
可以在本地停用。
啟用和關閉事件¶
為了監視事件,必須啟用它並註冊相應的回撥。可以透過全域性設定或為特定程式碼物件設定事件來啟用或關閉事件。
全域性設定事件¶
可以透過修改正在監視的事件集來全域性控制事件。
- sys.monitoring.set_events(tool_id: int, event_set: int, /) None ¶
啟用 event_set 中設定的所有事件。如果 tool_id 未使用,則引發
ValueError
。
預設情況下,沒有事件處於活動狀態。
每個程式碼物件事件¶
也可以在每個程式碼物件的基礎上控制事件。下面定義的接受 types.CodeType
的函式應該準備好接受來自未在 Python 中定義的函式的類似物件(請參閱 Monitoring C API)。
- sys.monitoring.set_local_events(tool_id: int, code: CodeType, event_set: int, /) None ¶
啟用 code 的 event_set 中設定的所有本地事件。如果 tool_id 未使用,則引發
ValueError
。
本地事件會新增到全域性事件中,但不會遮蔽全域性事件。換句話說,無論本地事件如何,所有全域性事件都將為程式碼物件觸發。
停用事件¶
- 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 註冊用於 event 的可呼叫物件 func。
如果為給定的 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
請注意,destination_offset 是程式碼接下來將執行的位置。對於未採用的分支,這將是分支後指令的偏移量。
-
func(code: CodeType, instruction_offset: int) -> DISABLE | Any