sys.monitoring --- Giám sát sự kiện thực thi

Added in version 3.12.


Ghi chú

sys.monitoring là một không gian tên trong mô-đun sys, không phải là mô-đun độc lập và import sys.monitoring sẽ không thành công với ModuleNotFoundError. Thay vào đó, chỉ cần import sys và sau đó sử dụng sys.monitoring.

Không gian tên này cung cấp quyền truy cập vào các chức năng và hằng số cần thiết để kích hoạt và kiểm soát việc giám sát sự kiện.

Khi chương trình thực thi, các sự kiện xảy ra có thể được các công cụ giám sát việc thực thi quan tâm. Không gian tên sys.monitoring cung cấp phương tiện để nhận lệnh gọi lại khi xảy ra sự kiện quan tâm.

Việc giám sát API bao gồm ba thành phần:

Mã định danh công cụ

Mã định danh công cụ là một số nguyên và tên liên quan. Mã nhận dạng công cụ được sử dụng để ngăn cản các công cụ can thiệp lẫn nhau và cho phép nhiều công cụ hoạt động cùng một lúc. Hiện tại các công cụ hoàn toàn độc lập và không thể sử dụng để giám sát lẫn nhau. Hạn chế này có thể được dỡ bỏ trong tương lai.

Trước khi đăng ký hoặc kích hoạt sự kiện, công cụ nên chọn một mã định danh. Mã định danh là các số nguyên trong phạm vi từ 0 đến 5.

Đăng ký và sử dụng công cụ

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

Phải được gọi trước khi tool_id có thể được sử dụng. tool_id phải nằm trong phạm vi từ 0 đến 5. Tăng ValueError nếu tool_id được sử dụng.

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

Hủy đăng ký tất cả các sự kiện và chức năng gọi lại liên quan đến tool_id.

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

Nên gọi khi công cụ không còn yêu cầu tool_id nữa. Sẽ gọi clear_tool_id() trước khi phát hành tool_id.

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

Trả về tên của công cụ nếu tool_id được sử dụng, nếu không nó sẽ trả về None. tool_id phải nằm trong phạm vi từ 0 đến 5.

Tất cả các ID đều được VM xử lý giống nhau đối với các sự kiện, nhưng các ID sau được xác định trước để giúp các công cụ hợp tác dễ dàng hơn:

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

Sự kiện

Các sự kiện sau được hỗ trợ:

sys.monitoring.events.BRANCH_LEFT

Một nhánh có điều kiện đi sang trái.

Công cụ này có quyền xác định cách trình bày các nhánh "trái" và "phải". Không có gì đảm bảo nhánh nào là "trái" và nhánh nào là "phải", ngoại trừ việc nó sẽ nhất quán trong suốt thời gian của chương trình.

sys.monitoring.events.BRANCH_RIGHT

Một nhánh có điều kiện đi sang phải.

sys.monitoring.events.CALL

Cuộc gọi bằng mã Python (sự kiện xảy ra trước cuộc gọi).

sys.monitoring.events.C_RAISE

Một ngoại lệ được tạo ra từ bất kỳ lệnh gọi nào, ngoại trừ các hàm Python (sự kiện xảy ra sau khi thoát).

sys.monitoring.events.C_RETURN

Trả về từ bất kỳ lệnh gọi nào, ngoại trừ các hàm Python (sự kiện xảy ra sau khi trả về).

sys.monitoring.events.EXCEPTION_HANDLED

Một ngoại lệ được xử lý.

sys.monitoring.events.INSTRUCTION

Một lệnh VM sắp được thực thi.

sys.monitoring.events.JUMP

Một bước nhảy vô điều kiện trong biểu đồ luồng điều khiển được thực hiện.

sys.monitoring.events.LINE

Một lệnh sắp được thực thi có số dòng khác với lệnh trước đó.

sys.monitoring.events.PY_RESUME

Tiếp tục hàm Python (dành cho hàm tạo và hàm coroutine), ngoại trừ lệnh gọi throw().

sys.monitoring.events.PY_RETURN

Trả về từ hàm Python (xảy ra ngay trước khi trả về, khung của callee sẽ nằm trên ngăn xếp).

sys.monitoring.events.PY_START

Bắt đầu một hàm Python (xảy ra ngay sau lệnh gọi, khung của callee sẽ nằm trên ngăn xếp)

sys.monitoring.events.PY_THROW

Hàm Python được tiếp tục bằng lệnh gọi throw().

sys.monitoring.events.PY_UNWIND

Thoát khỏi hàm Python trong quá trình gỡ bỏ ngoại lệ. Điều này bao gồm các ngoại lệ được đưa ra trực tiếp trong hàm và được phép tiếp tục phổ biến.

sys.monitoring.events.PY_YIELD

Năng suất từ một hàm Python (xảy ra ngay trước năng suất, khung của callee sẽ nằm trên ngăn xếp).

sys.monitoring.events.RAISE

Một ngoại lệ được nêu ra, ngoại trừ những trường hợp gây ra sự kiện STOP_ITERATION.

sys.monitoring.events.RERAISE

Một ngoại lệ được đưa ra lại, ví dụ như ở cuối khối finally.

sys.monitoring.events.STOP_ITERATION

Một StopIteration nhân tạo được nâng lên; xem the STOP_ITERATION event.

Nhiều sự kiện có thể được thêm vào trong tương lai.

Những sự kiện này là thuộc tính của không gian tên sys.monitoring.events. Mỗi sự kiện được biểu diễn dưới dạng hằng số nguyên lũy thừa 2. Để xác định một tập hợp các sự kiện, chỉ cần thực hiện theo từng bit HOẶC các sự kiện riêng lẻ cùng nhau. Ví dụ: để chỉ định cả hai sự kiện PY_RETURNPY_START, hãy sử dụng biểu thức PY_RETURN | PY_START.

sys.monitoring.events.NO_EVENTS

Bí danh cho 0 để người dùng có thể so sánh rõ ràng như:

nếu get_events(DEBUGGER_ID) == NO_EVENTS:
    ...

Việc đặt sự kiện này sẽ hủy kích hoạt tất cả các sự kiện.

Sự kiện địa phương

Các sự kiện cục bộ gắn liền với việc thực thi bình thường của chương trình và xảy ra tại các vị trí được xác định rõ ràng. Tất cả các sự kiện địa phương có thể bị vô hiệu hóa. Các sự kiện địa phương là:

Sự kiện không được dùng nữa

  • BRANCH

Sự kiện BRANCH không được dùng nữa trong phiên bản 3.14. Sử dụng các sự kiện BRANCH_LEFTBRANCH_RIGHT sẽ cho hiệu suất tốt hơn nhiều vì chúng có thể bị vô hiệu hóa một cách độc lập.

Sự kiện phụ trợ

Các sự kiện phụ trợ có thể được theo dõi như các sự kiện khác, nhưng được kiểm soát bởi một sự kiện khác:

Các sự kiện C_RETURNC_RAISE được kiểm soát bởi sự kiện CALL. C_RETURNC_RAISE sự kiện sẽ chỉ được nhìn thấy nếu sự kiện CALL tương ứng đang được theo dõi.

Sự kiện khác

Các sự kiện khác không nhất thiết phải gắn với một vị trí cụ thể trong chương trình và không thể tắt riêng lẻ thông qua DISABLE.

Các sự kiện khác có thể được theo dõi là:

Sự kiện STOP_ITERATION

PEP 380 chỉ định rằng ngoại lệ StopIteration được đưa ra khi trả về giá trị từ trình tạo hoặc coroutine. Tuy nhiên, đây là một cách rất kém hiệu quả để trả về một giá trị, vì vậy một số triển khai Python, đặc biệt là CPython 3.12+, không đưa ra một ngoại lệ trừ khi nó hiển thị với mã khác.

Để cho phép các công cụ giám sát các trường hợp ngoại lệ thực sự mà không làm chậm trình tạo và coroutine, sự kiện STOP_ITERATION được cung cấp. STOP_ITERATION có thể bị vô hiệu hóa cục bộ, không giống như RAISE.

Lưu ý rằng sự kiện STOP_ITERATION và sự kiện RAISE cho ngoại lệ StopIteration là tương đương và được coi là có thể hoán đổi cho nhau khi tạo sự kiện. Việc triển khai sẽ ưu tiên STOP_ITERATION vì lý do hiệu suất, nhưng có thể tạo ra sự kiện RAISE với StopIteration.

Bật và tắt sự kiện

Để theo dõi một sự kiện, nó phải được bật và phải đăng ký cuộc gọi lại tương ứng. Bạn có thể bật hoặc tắt các sự kiện bằng cách đặt các sự kiện trên toàn cầu và/hoặc cho một đối tượng mã cụ thể. Một sự kiện sẽ chỉ kích hoạt một lần, ngay cả khi nó được bật cả trên toàn cầu và cục bộ.

Đặt sự kiện trên toàn cầu

Các sự kiện có thể được kiểm soát trên toàn cầu bằng cách sửa đổi tập hợp các sự kiện đang được theo dõi.

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

Trả về int đại diện cho tất cả các sự kiện đang hoạt động.

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

Kích hoạt tất cả các sự kiện được đặt trong event_set. Tăng ValueError nếu tool_id không được sử dụng.

Không có sự kiện nào được kích hoạt theo mặc định.

Mỗi sự kiện đối tượng mã

Các sự kiện cũng có thể được kiểm soát trên cơ sở từng đối tượng mã. Các hàm được xác định bên dưới chấp nhận types.CodeType phải được chuẩn bị để chấp nhận một đối tượng trông giống nhau từ các hàm không được xác định trong Python (xem Giám sát C API).

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

Trả về tất cả local events cho code

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

Kích hoạt tất cả local events cho code được đặt trong event_set. Tăng ValueError nếu tool_id không được sử dụng.

Vô hiệu hóa sự kiện

sys.monitoring.DISABLE

Một giá trị đặc biệt có thể được trả về từ hàm gọi lại để tắt các sự kiện cho vị trí mã hiện tại.

Local events có thể bị vô hiệu hóa đối với một vị trí mã cụ thể bằng cách trả về sys.monitoring.DISABLE từ hàm gọi lại. Điều này không thay đổi sự kiện nào được đặt hoặc bất kỳ vị trí mã nào khác cho cùng một sự kiện.

Việc vô hiệu hóa các sự kiện cho các vị trí cụ thể là rất quan trọng để giám sát hiệu suất cao. Ví dụ: một chương trình có thể được chạy trong trình gỡ lỗi mà không cần chi phí hoạt động nếu trình gỡ lỗi vô hiệu hóa tất cả hoạt động giám sát ngoại trừ một số điểm dừng.

Nếu DISABLE được trả về bằng lệnh gọi lại cho global event, thì ValueError sẽ được trình thông dịch đưa ra ở một vị trí không cụ thể (nghĩa là sẽ không cung cấp dấu vết).

sys.monitoring.restart_events() None

Kích hoạt tất cả các sự kiện đã bị sys.monitoring.DISABLE tắt cho tất cả các công cụ.

Đăng ký chức năng gọi lại

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

Đăng ký func có thể gọi cho event với tool_id đã cho

Nếu một lệnh gọi lại khác đã được đăng ký cho tool_idevent nhất định thì lệnh gọi lại đó sẽ không được đăng ký và được trả về. Nếu không thì register_callback() trả về None.

Tăng một auditing event sys.monitoring.register_callback với đối số func.

Các chức năng có thể được hủy đăng ký bằng cách gọi sys.monitoring.register_callback(tool_id, event, None).

Chức năng gọi lại có thể được đăng ký và hủy đăng ký bất cứ lúc nào.

Lệnh gọi lại chỉ được gọi một lần bất kể sự kiện có được bật cả trên toàn cầu và cục bộ hay không. Do đó, nếu mã của bạn có thể bật một sự kiện cho cả sự kiện toàn cầu và cục bộ thì lệnh gọi lại cần phải được viết để xử lý một trong hai trình kích hoạt.

Đối số hàm gọi lại

sys.monitoring.MISSING

Một giá trị đặc biệt được truyền cho hàm gọi lại để cho biết rằng không có đối số nào cho cuộc gọi.

Khi một sự kiện hoạt động xảy ra, hàm gọi lại đã đăng ký sẽ được gọi. Các hàm gọi lại trả về một đối tượng không phải là DISABLE sẽ không có hiệu lực. Các sự kiện khác nhau sẽ cung cấp cho hàm gọi lại các đối số khác nhau, như sau:

  • PY_STARTPY_RESUME:

    func(code: CodeType,guide_offset: int) -> đối tượng
    
  • PY_RETURNPY_YIELD:

    func(code: CodeType,guide_offset: int, retval: object) -> đối tượng
    
  • CALL, C_RAISEC_RETURN (arg0 có thể là MISSING cụ thể):

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

    code đại diện cho đối tượng mã nơi cuộc gọi đang được thực hiện, trong khi callable là đối tượng sắp được gọi (và do đó đã kích hoạt sự kiện). Nếu không có đối số, arg0 được đặt thành sys.monitoring.MISSING.

    Đối với các phương thức phiên bản, callable sẽ là đối tượng hàm như được tìm thấy trên lớp với arg0 được đặt thành phiên bản (tức là đối số self cho phương thức).

  • RAISE, RERAISE, EXCEPTION_HANDLED, PY_UNWIND, PY_THROWSTOP_ITERATION:

    func(code: CodeType,guide_offset: int, ngoại lệ: BaseException) -> đối tượng
    
  • LINE:

    func(code: CodeType, line_number: int) -> đối tượng
    
  • BRANCH_LEFT, BRANCH_RIGHTJUMP:

    func(code: CodeType,guide_offset: int, Destination_offset: int) -> đối tượng
    

    Lưu ý rằng destination_offset là nơi mã sẽ thực thi tiếp theo.

  • INSTRUCTION:

    func(code: CodeType,guide_offset: int) -> đối tượng