Sys.monitoring API doesn't always callback on CALL events

Depending on how I define foo below, I can change whether the monitoring API gives be the callback I asked for. Is this a bug? This is on 3.12.3.

Full reproducer:

#!/usr/bin/env python

import sys
from types import CodeType
from typing import Any

def _callback(
    code: CodeType,
    instruction_offset: int,
    callable: object,
    arg0: object
) -> Any:
    print(f"{code.co_name=} {code.co_qualname=} {code.co_filename=}")

for i in range(5):
    try:
        sys.monitoring.use_tool_id(i, "call_tracking")
        _TOOL_ID = i
        break
    except ValueError:
        continue
else:
    raise RuntimeError("No free tool IDs available for call tracking!")

dummy = 1

if __name__ == "__main__":
    sys.monitoring.register_callback(_TOOL_ID, sys.monitoring.events.CALL, _callback)

    # the callback won't fire with this version!
    #def foo(): pass

    # the callback won't fire with this version either!
    # def foo():
    #     global dummy
    #     dummy += 1

    # but it will with this version
    def foo():
        print("hello")

    sys.monitoring.set_local_events(_TOOL_ID, foo.__code__, sys.monitoring.events.CALL)

    foo()

You are asking it to monitor for calls inside of foo.__code__. If you look at callable, you can see it points to the print function.

1 Like

Oh I misunderstood, looks like I want PY_START