Compatibility with sys.settrace

Pyccolo supports not only AST-level instrumentation, but also instrumentation built on Python’s built-in tracing utilities. To use it, register handlers for one of the corresponding Pyccolo events: call, line, return_, exception, or opcode.

import pyccolo as pyc


class SysTracer(pyc.BaseTracer):
    @pyc.call
    def handle_call(self, *_, **__):
        print("Pushing a stack frame!")

    @pyc.return_
    def handle_return(self, *_, **__):
        print("Popping a stack frame!")


if __name__ == "__main__":
    with SysTracer:
        def f():
            def g():
                return 42
            return g()
        # push, push, pop, pop
        answer_to_life_universe_everything = f()

No pyc.exec required

Notice that we did not need pyccolo.exec() here, because Python’s built-in tracing does not involve any AST-level transformation — the handlers attach through sys.settrace at runtime, not by rewriting source. (If we had also registered handlers for AST events such as pyc.before_stmt, we would need pyc.exec to instrument code in the same file where the tracer is defined; see Quickstart.)

Note

The opcode event requires Python >= 3.7.

Composing with an existing settrace function

Pyccolo composes with an existing sys.settrace(...) function, too. Its unit tests for call and return_ pass even when coverage.py is active — and without breaking it — even though coverage.py also drives Python’s built-in tracing.