laike9m
laike9m

Reputation: 19328

Why doesn't sys.settrace fire when there's no main function?

import sys

def printer(frame, event, arg):
    print(frame, event, arg)
    return printer

sys.settrace(printer)
x = 1
sys.settrace(None)

The above code won't print anything. https://repl.it/@laike9m/settrace

If I create a main function and put x = 1 into it, things work as expected

import sys

def printer(frame, event, arg):
    print(frame, event, arg)
    return printer

sys.settrace(printer)

def main():
    x = 1

if __name__ == '__main__':
    main()
    sys.settrace(None)
    # outputs
    # <frame object at 0x7f16e5264d88> call None
    # <frame object at 0x7f16e5264d88> line None
    # <frame object at 0x7f16e5264d88> return None

https://repl.it/@laike9m/settracehasmain

I'm using Python 3.6+

Upvotes: 4

Views: 553

Answers (1)

TrebledJ
TrebledJ

Reputation: 8987

Docs time!

>>> import sys
>>> help(sys.settrace)

settrace(...)
    settrace(function)

    Set the global debug tracing function.  It will be called on each
    function call.  See the debugger chapter in the library manual.

The key-phrase here is "function call". main() is a function call. x = 1 isn't. Simply put, sys.settrace does fire, but the tracing function isn't called when there is no function call.


Interestingly, the official docs word it differently:

The trace function is invoked (with event set to 'call') whenever a new local scope is entered; it should return a reference to a local trace function to be used that scope, or None if the scope shouldn’t be traced.

(Emphasis added.)

Since calling a function enters a local scope, the trace function will be invoked. But in addition to calling functions, the docs state that other forms of local scope also work:

import sys

def printer(frame, event, arg):
    print(frame, event, arg)
    return printer

sys.settrace(printer)

class A:
    print(1)

sys.settrace(None)

Output (some paths replaced by ... by hand):

<frame at 0x7fa1a4d184b0, file '/.../example.py', line 9, code A> call None
<frame at 0x7fa1a4d184b0, file '/.../example.py', line 9, code A> line None
<frame at 0x7fa1a4d184b0, file '/.../example.py', line 10, code A> line None
1
<frame at 0x7fa1a4d184b0, file '/.../example.py', line 10, code A> return None

Upvotes: 4

Related Questions