使用pycallgraph和graphviz查看函数调用图
- 前言
- 一、pycallgraph是什么?
- 二、使用步骤
- 1.安装步骤
- 2.引入库
- 3.进阶使用
前言
对于python开发者而言,我们常常会遇到这样的问题:当代码很长,或者代码的整体逻辑混乱的时候,调试代码就会非常困难,如果有一个模块能把代码的结构可视化,对开发者而言就会带来很大的便利。pycallgraph和graphviz就可以实现这一效果,生成函数调用图。
一、pycallgraph是什么?
Python Call Graph成为了Python应用程序的可视化分析工具。它使用一个名为sys.set_trace()的调试Python函数,该函数在您的代码每次进入或离开函数时都会进行回调。这样,Python调用图就可以跟踪每个被调用函数的名称,以及哪个函数被调用,哪个函数花费的时间,调用次数等。
它能够生成不同类型的输出和可视化。最初,Python Call Graph仅用于生成GraphViz的DOT文件,从1.0.0版开始,它还可以生成JSON文件和Gephi的GDF文件。通过对Output类进行子类化,创建自定义输出相当容易。
Graphviz是开源的图形可视化软件。它具有几个主要的图形布局程序。
二、使用步骤
1.安装步骤
安装pycallgraph
pip install pycallgraph
安装graphviz
http://www.graphviz.org/download/
选择合适版本安装,安装过程中需要选择添加环境变量
安装完成后检查环境变量:
命令行查看是否可以使用以及安装位置
在vscode中使用需要添加环境变量:
ctrl + shift + P 快捷键打开
打开后,如图加入环境变量,即可使用了。
2.引入库
代码如下(示例):
from pycallgraph import PyCallGraph
from pycallgraph.output import GraphvizOutput
class Banana:
def eat(self):
pass
class Person:
def __init__(self):
self.no_bananas()
def no_bananas(self):
self.bananas = []
def add_banana(self, banana):
self.bananas.append(banana)
def eat_bananas(self):
[banana.eat() for banana in self.bananas]
self.no_bananas()
def main():
graphviz = GraphvizOutput()
graphviz.output_file = 'basic.png'
with PyCallGraph(output=graphviz):
person = Person()
for a in range(10):
person.add_banana(Banana())
person.eat_bananas()
if __name__ == '__main__':
main()
下面是效果图:
3.进阶使用
过滤器
• include 流程图中只包含能和include定义内容匹配上的函数
• exclude 流程图中不包含能和include定义内容匹配上的函数
• max_depth 保留调用层级
from pycallgraph import PyCallGraph
from pycallgraph import Config
from pycallgraph import GlobbingFilter
from pycallgraph.output import GraphvizOutput
from banana import Banana
config = Config()
config.trace_filter = GlobbingFilter(exclude=[
'pycallgraph.*',
'*.secret_function',
])
graphviz = GraphvizOutput(output_file='filter_exclude.png')
with PyCallGraph(output=graphviz, config=config):
banana = Banana()
banana.eat()
from pycallgraph import PyCallGraph
from pycallgraph import Config
from pycallgraph.output import GraphvizOutput
from banana import Banana
config = Config(max_depth=1)
graphviz = GraphvizOutput(output_file='filter_max_depth.png')
with PyCallGraph(output=graphviz, config=config):
banana = Banana()
banana.eat()