May-16-2017, 05:28 PM
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:
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
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>
---------------------------------------------------------