有没有办法可视化一组python函数中的调用关系?

问题描述

假设你有一个文件夹,里面有很多 python 模块,每个模块都包含函数。我想用顶点 = 函数名称可视化图形。我想如下定义边:如果函数 F1 调用 F2,则 F1 的顶点通过有向边连接到 F2。

单个模块的最小示例:

# --- module.py ---

def F1():
    pass

def F2():
    F1()

def F3():
    F1()

def F4():
    F2()

所需的输出将是一个具有顶点:V = {F1,F2,F3,F4} 和边 E = {F2->F1,F3->F1,F4->F2} 的图。

有没有方便的图书馆来做到这一点?否则我想我可以将模块转换为字符串,识别函数并使用一些正则表达式查找内部调用

谢谢

解决方法

不确定它是否是一个 100% 的工作模型,但它有望成为一个起点。这背后的想法是使用装饰器来更新字典 graph 的值基于 inspect.currentframeinspect.getouterframesThis answer(解释如何获取调用者的姓名)稍作修改以获取结果。

入口点称为 '<module>',因此如果您只关心函数相互调用,您可能可以从图中丢弃它。

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)

输出

{'<module>': {'f2'},'f2': {'f1','f3'},'f3': {'f1'}}