pygraphviz-画出程序调用栈图

pygraphviz 学习

install

1. dnf install graphviz-devel
2. dnf install graphviz
3. pip install pygraphviz

使用

pygraphviz 是对 graphviz的封装
可以很方便的用来画图

可以用下面的方法 画出程序的调用堆栈

from flask import Flask

app = Flask(name)

@app.route(‘/‘)
def index():
from utils import cheese # 下面附上utils模块的实现
cheese()
return ‘Yet another hello!’

if name == ‘main‘:

app.run()

最后贴上那个utils.py的源码,记得安装必要的依赖:

from future import unicode_literals

def cheese(frame=None, slient=False):
import sys
import tempfile
import webbrowser
import pygraphviz as pgv

if not frame:
    frame = sys._getframe().f_back

G = pgv.AGraph(strict=False, directed=True)

stack = []

node_set = set()
subgraph_set = {}

while frame:
    filename = frame.f_code.co_filename
    firstlineno = frame.f_code.co_firstlineno
    function = frame.f_code.co_name

    node = '{0}:{1}:{2}'.format(filename, firstlineno, function)
    if node not in node_set:
        node_set.add(node)
        if filename not in subgraph_set:
            subgraph_set[filename] = G.add_subgraph(
                name='cluster' + filename,
                label=filename
            )
        subgraph = subgraph_set[filename]
        subgraph.add_node(
            node,
            label='{0}:{1}'.format(firstlineno, function)
        )

    stack.append(frame)
    frame = frame.f_back

stack.reverse()

len_stack = len(stack)

for index, start in enumerate(stack):

    if index + 1 < len_stack:
        start_filename = start.f_code.co_filename
        start_firstlineno = start.f_code.co_firstlineno
        start_function = start.f_code.co_name
        start_lineno = start.f_lineno
        start_subgraph = subgraph_set[start_filename]

        end = stack[index + 1]
        end_filename = end.f_code.co_filename
        end_firstlineno = end.f_code.co_firstlineno
        end_function = end.f_code.co_name
        end_subgraph = subgraph_set[end_filename]

        if index == 0:
            color = 'green'
        elif index == len_stack - 2:
            color = 'red'
        else:
            color = 'black'

        G.add_edge(
            '{0}:{1}:{2}'.format(start_filename,
                                 start_firstlineno,
                                 start_function),
            '{0}:{1}:{2}'.format(end_filename,
                                 end_firstlineno,
                                 end_function),
            color=color,
            ltail=start_subgraph.name,
            lhead=end_subgraph.name,
            label='#{0} at {1}'.format(index + 1, start_lineno)
        )

fd, name = tempfile.mkstemp('.png')

G.draw(name, prog='dot')
G.close()

if not slient:
    webbrowser.open('file://' + name)

return name