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。
- 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(包括 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_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¶
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;參見 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: ...
設定此事件將停用所有事件。
區域性事件¶
區域性事件與程式的正常執行相關聯,併發生在明確定義的位置。所有區域性事件都可以停用。區域性事件包括
已棄用的事件¶
BRANCH
BRANCH 事件在 3.14 中已棄用。使用 BRANCH_LEFT 和 BRANCH_RIGHT 事件將提供更好的效能,因為它們可以獨立停用。
輔助事件¶
輔助事件可以像其他事件一樣被監控,但由另一個事件控制
C_RETURN 和 C_RAISE 事件由 CALL 事件控制。C_RETURN 和 C_RAISE 事件只有在監控相應的 CALL 事件時才可見。
其他事件¶
其他事件不一定與程式中的特定位置繫結,並且無法單獨停用。
可以監控的其他事件包括
STOP_ITERATION 事件¶
PEP 380 指定從生成器或協程返回一個值時會引發 StopIteration 異常。然而,這是一種非常低效的返回值方式,因此一些 Python 實現,特別是 CPython 3.12+,除非異常對其他程式碼可見,否則不會引發異常。
為了允許工具監控真實的異常而不會減慢生成器和協程的速度,提供了 STOP_ITERATION 事件。STOP_ITERATION 可以區域性停用,不像 RAISE。
請注意,STOP_ITERATION 事件和 StopIteration 異常的 RAISE 事件是等效的,並且在生成事件時被視為可互換。出於效能原因,實現將優先選擇 STOP_ITERATION,但可能會生成帶有 StopIteration 的 RAISE 事件。
開啟和關閉事件¶
為了監控事件,必須開啟它並註冊相應的回撥。可以透過全域性和/或針對特定程式碼物件設定事件來開啟或關閉事件。即使事件全域性和區域性都開啟,它也只會觸發一次。
全域性設定事件¶
可以透過修改受監控的事件集來全域性控制事件。
- sys.monitoring.set_events(tool_id: int, event_set: int, /) None¶
啟用在 event_set 中設定的所有事件。如果 tool_id 未在使用中,則引發
ValueError。
預設情況下沒有事件是活動的。
每個程式碼物件事件¶
事件也可以按每個程式碼物件進行控制。下面定義的接受 types.CodeType 的函式應該準備好接受來自非 Python 定義函式(參見 監控 C API)的類似物件。
停用事件¶
- 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,其引數為func。
可以透過呼叫 sys.monitoring.register_callback(tool_id, event, None) 來取消註冊函式。
回撥函式可以隨時註冊和取消註冊。
無論事件是全域性還是區域性開啟,回撥都只調用一次。因此,如果您的程式碼可以同時為全域性和區域性事件開啟一個事件,那麼回撥需要編寫以處理任一觸發器。
回撥函式引數¶
- sys.monitoring.MISSING¶
一個特殊值,傳遞給回撥函式以指示呼叫沒有引數。
當活動事件發生時,會呼叫已註冊的回撥函式。返回除 DISABLE 之外的物件的函式將不起作用。不同的事件將向回撥函式提供不同的引數,如下所示
-
func(code: CodeType, instruction_offset: int) -> object
-
func(code: CodeType, instruction_offset: int, retval: object) -> object
CALL、C_RAISE和C_RETURN(arg0 可以專門是MISSING)func(code: CodeType, instruction_offset: int, callable: object, arg0: object) -> object
code 表示正在進行呼叫的程式碼物件,而 callable 是即將被呼叫(並因此觸發事件)的物件。如果沒有引數,arg0 將設定為
sys.monitoring.MISSING。對於例項方法,callable 將是類上找到的函式物件,arg0 設定為例項(即方法的
self引數)。RAISE、RERAISE、EXCEPTION_HANDLED、PY_UNWIND、PY_THROW和STOP_ITERATIONfunc(code: CodeType, instruction_offset: int, exception: BaseException) -> object
LINE:func(code: CodeType, line_number: int) -> object
BRANCH_LEFT、BRANCH_RIGHT和JUMPfunc(code: CodeType, instruction_offset: int, destination_offset: int) -> object
請注意,destination_offset 是程式碼接下來將執行的位置。
-
func(code: CodeType, instruction_offset: int) -> object