Reputation: 817
Imagine you have a folder with many python modules and each of them contains functions. I would like to visualize a graph with vertices = function names. I want to define the edges as follows: if function F1 calls F2 then the vertex of F1 is connected to F2 with a directed edge.
Minimal example with a single module:
# --- module.py ---
def F1():
pass
def F2():
F1()
def F3():
F1()
def F4():
F2()
The desired output would be a graph with vertices: V = {F1, F2, F3, F4}
and edges E = {F2->F1, F3->F1, F4->F2}
.
Is there a convenient library to do this? Otherwise I imagine I can covert the module to string, identify the functions and find internal calls with some regex expressions.
Thanks
Upvotes: 2
Views: 1109
Reputation: 7073
Not exactly sure if it's a 100% working model but it can hopefully be of some starting point. The idea behind this is to use a decorator that is going to update a dictionary graph
with values based on inspect.currentframe
and inspect.getouterframes
. This answer (explains how to get the name of the caller) was modified slightly to get the results.
The entry point is called '<module>'
so you can probably discard that from your graph if you only care about functions calling each other.
import inspect
from collections import defaultdict
graph = defaultdict(set)
def called(fun):
def inner(*args, **kwargs):
cur_frame = inspect.currentframe()
cal_frame = inspect.getouterframes(cur_frame)
graph[cal_frame[1].function].add(fun.__name__)
return fun(*args, **kwargs)
return inner
@called
def f1():
pass
@called
def f2():
f1()
f3()
@called
def f3():
f1()
@called
def f4():
f2()
v = {f1, f2, f3, f4}
f2()
print(graph)
Output
{'<module>': {'f2'}, 'f2': {'f1', 'f3'}, 'f3': {'f1'}}
Upvotes: 1