How can I step to use the python debugger to break at every function call?
Question: I want to closely monitor the chain of function calls which are called from a
certain function.

    
    
    import pdb; pdb.set_trace()
    res = api.InsertVideoEntry(video_entry, video)
    

I'm looking for a way to easily see that `api.insertVideoEntry(video_entry,
video)` calls `foo()` which calls `bar()` which calls `baz()`,

Here's a really crude diagram to show what I mean. I don't need it in this
form, but this is the kind kind of information I'm looking for.

    
    
    api.insertVideoEntry()
        foo()
            bar()
                baz()
                baz2()
            log()
        finish()
    


Answer: This was an interesting learning experience to write up. Maybe you can use the
code shown here? [This demonstration](http://ideone.com/W3scL) should give you
an idea of the type of output you can expect when using `trace`.

    
    
    # Functions to trace
    # ==================
    
    def baz():
        pass
    
    def baz2():
        pass
    
    def bar():
        baz()
        baz2()
    
    def log():
        pass
    
    def foo():
        bar()
        log()
    
    def finish():
        pass
    
    def insertVideoEntry():
        foo()
        finish()
    
    # Names to trace
    # ==============
    
    names = list(locals())
    
    # Machinery for tracing
    # =====================
    
    import os
    import sys
    
    def trace(start, *names):
        def tracefunc(frame, event, arg):
            if event == 'call':
                code = frame.f_code
                name = code.co_name
                if name in names:
                    level = -start
                    while frame:
                        frame = frame.f_back
                        level += 1
                    print('{}{}.{}()'.format(
                        '    ' * level,
                        os.path.splitext(os.path.basename(code.co_filename))[0],
                        name))
                    return tracefunc
        sys.settrace(tracefunc)
    
    # Demonstration of tracing
    # ========================
    
    trace(2, *names)
    
    insertVideoEntry()
    

If you are interested in a recursive demo, you might like [this
variation](http://ideone.com/ltcnQ8) with a called arguments readout:

    
    
    import os
    import sys
    
    def main(discs):
        a, b, c = list(range(discs, 0, -1)), [], []
        line = '-' * len(repr(a))
        print(a, b, c, sep='\n')
        for source, destination in towers_of_hanoi(discs, a, b, c):
            destination.append(source.pop())
            print(line, a, b, c, sep='\n')
    
    def towers_of_hanoi(count, source, via, destination):
        if count > 0:
            count -= 1
            yield from towers_of_hanoi(count, source, destination, via)
            yield source, destination
            yield from towers_of_hanoi(count, via, source, destination)
    
    def trace(start, *names):
        def tracefunc(frame, event, arg):
            if event == 'call':
                code = frame.f_code
                name = code.co_name
                if name in names:
                    level = -start
                    args = ', '.join(repr(frame.f_locals[name]) for name in
                                     code.co_varnames[:code.co_argcount])
                    while frame:
                        frame = frame.f_back
                        level += 1
                    print('{}{}.{}({})'.format(
                        ' ' * (level * 4),
                        os.path.splitext(os.path.basename(code.co_filename))[0],
                        name, args))
                    return tracefunc
        sys.settrace(tracefunc)
    
    if __name__ == '__main__':
        trace(3, 'main', 'towers_of_hanoi')
        main(3)
    

