Skip to content

Instantly share code, notes, and snippets.

@jcaesar
Last active April 7, 2022 08:22
Show Gist options
  • Save jcaesar/99f32936dd0f191d2e5d0eeb465be631 to your computer and use it in GitHub Desktop.
Save jcaesar/99f32936dd0f191d2e5d0eeb465be631 to your computer and use it in GitHub Desktop.
Snippet to paste before your python code to get a call graph
# Place at the head of your main file
import sys
import atexit
def function_identifier(frame):
code = frame.f_code
name = code.co_name
file = code.co_filename
return "{}:{}".format(file, name)
cg = {}
def trace_calls(frame, event, arg):
if event != 'call':
return
if frame.f_code.co_name == "print_calls":
return
global cg
caller_f = frame.f_back
yeh = "/opt/foo-demo/" # Wherever your code lives
nyeh = "<frozen importlib."
if frame.f_code.co_filename.startswith(nyeh):
return
while caller_f.f_back is not None and str(caller_f.f_code.co_filename).startswith(nyeh):
caller_f = caller_f.f_back
if caller_f.f_code.co_filename.startswith(nyeh):
return
callee = function_identifier(frame)
caller = function_identifier(caller_f)
if (not caller.startswith(yeh)) and (not callee.startswith(yeh)):
return
if caller in cg:
cg[caller].add(callee)
else:
cg[caller] = {callee}
def print_calls():
global gc
print()
print("digraph G {")
print(" rankdir=\"LR\";")
for caller, callees in cg.items():
for callee in callees:
print(" \"{}\" -> \"{}\"".format(caller, callee))
print("}")
sys.settrace(trace_calls)
atexit.register(print_calls)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment