Say I have a piece of code like this:
import sys
def printer(frame, event, arg):
print(frame, event, arg)
return printer
sys.settrace(printer)
x = 1
sys.settrace(None)
Since
The trace function is invoked (with event set to 'call') whenever a new local scope is entered
The above code outputs nothing. See my previous question.
So is there a way to trace lines in global scope, like x = 1?
sys.settrace sets the global trace function. This trace function is the one invoked whenever a new Python stack frame is entered ('call' events), and its return value is the new scope's local trace function. The local trace function of the active stack frame is the one used for all other event types.
You need to set the local trace function of an existing stack frame, but setting the global trace function doesn't help you do that. To set an existing frame's local trace function, you can manually assign the f_trace attribute of the frame object to the function you want. For example, to set the current frame's local trace function:
import sys
sys._getframe().f_trace = whateverfunc
Note that local trace functions will not be invoked if there is no global trace function, so you need to set the global trace function too. (This doesn't seem to be documented.)
You can combine sys.settrace and manual f_trace assignment to trace both new and existing stack frames; for example, on a 'return' event, you can check the local trace function of the frame you're about to return to and set that trace function to whatever you want. The bdb debugger framework source code is a good example of how to work with trace functions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With