Python Forum
Walking the python call stack without leaks
Thread Rating:
  • 1 Vote(s) - 5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Walking the python call stack without leaks
#1
If you ever wondered how the call traceback works, you need to know how the python code stack
is structured.

Each frame in the python call stack is make up of the following items:
  • frame - previous frame in call stack (if any)
  • filename - full path of file containing executed code
  • lineno - The line number of the code from filename
  • function - function executed (or <module> )
  • code_context - a list of lines of context from the source code
  • index - index of
this code will traverse that stack:
import inspect


class ReverseEngineerCode:
   def __init__(self):
       self.full_stack = inspect.stack()
       self.this_module = __file__
       self.recursion_level = 0
       self.max_recursion_level = 2000

   def follow_frame(self, fframe):
       if self.recursion_level <= self.max_recursion_level:
           try:
               for group in fframe:
                   if group.code_context is None:
                       continue
                   if group.filename == self.this_module and group.function == '__init__':
                       continue
                   print('group.filename level-{}: {}'.format(self.recursion_level, group.filename))
                   print('group.lineno level-{}: {}'.format(self.recursion_level, group.lineno))
                   print('group.function level-{}: {}'.format(self.recursion_level, group.function))
                   print('group.code_contextlevel-{}:'.format(self.recursion_level))
                   for line in group.code_context:
                       print(line)
                   print('group.index level-{}: {}'.format(self.recursion_level, group.index))
                   print('group.frame level-{}: {}'.format(self.recursion_level, group.frame))
                   print('---------------------------------------------------------\n')
                   if inspect.isfunction(group.function):
                       self.recursion_level += 1
                       self.follow_frame(group.frame)
           except:
               print("Unexpected error:", sys.exc_info()[0])
           finally:
               del fframe


   def start_trace(self):
       self.recursion_level = 0
       self.follow_frame(self.full_stack)

def function1():
   te = ReverseEngineerCode()
   te.start_trace()

def function3():
   function1()


def function2():
   function3()


def main():
   function2()


if __name__ == '__main__':
   main()
results from the example:
Output:
group.filename level-0: M:/python/q-t/r/ReverseEngineerCode/ReverseEngineerCode/src/ReverseEngineerCode.py group.lineno level-0: 42 group.function level-0: function1 group.code_contextlevel-0:    te = ReverseEngineerCode() group.index level-0: 0 group.frame level-0: <frame object at 0x00000000023F4AF8> --------------------------------------------------------- group.filename level-0: M:/python/q-t/r/ReverseEngineerCode/ReverseEngineerCode/src/ReverseEngineerCode.py group.lineno level-0: 47 group.function level-0: function3 group.code_contextlevel-0:    function1() group.index level-0: 0 group.frame level-0: <frame object at 0x0000000001ED45B8> --------------------------------------------------------- group.filename level-0: M:/python/q-t/r/ReverseEngineerCode/ReverseEngineerCode/src/ReverseEngineerCode.py group.lineno level-0: 52 group.function level-0: function2 group.code_contextlevel-0:    function3() group.index level-0: 0 group.frame level-0: <frame object at 0x00000000023FB048> --------------------------------------------------------- group.filename level-0: M:/python/q-t/r/ReverseEngineerCode/ReverseEngineerCode/src/ReverseEngineerCode.py group.lineno level-0: 56 group.function level-0: main group.code_contextlevel-0:    function2() group.index level-0: 0 group.frame level-0: <frame object at 0x00000000022E2E98> --------------------------------------------------------- group.filename level-0: M:/python/q-t/r/ReverseEngineerCode/ReverseEngineerCode/src/ReverseEngineerCode.py group.lineno level-0: 60 group.function level-0: <module> group.code_contextlevel-0:    main() group.index level-0: 0 group.frame level-0: <frame object at 0x0000000000558A20> ---------------------------------------------------------
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020