前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Pygraphviz

Pygraphviz

原创
作者头像
vanguard
修改2021-01-04 10:57:43
5320
修改2021-01-04 10:57:43
举报
文章被收录于专栏:vanguardvanguard

代码越来越复杂,为了理清架构,需要搞清楚现有代码业务逻辑,没有很顺手的工具,简单写写学习一下。

首先用pygraphviz绘制一下处理好的关系数据,包含可能有重复的生产者和对应的消费者(角色可以交叉)。

每个不重复的生产者和消费者是一个节点,两者关系是一条边。

代码语言:javascript
复制
#!/usr/bin/python3
import pygraphviz as pyg

def read(path):
    print("start to read source ...")
    with open(path) as f: return f.readlines()

def nodes_edges(data):
    print("start to process data ...")
    nodes, edges = [], []
    for line in data:
        [a,b] = line.split(",")
        a = a.replace(" ",""); b = b.replace(" ","")
        if not a in nodes: nodes.append(a)
        if not b in nodes: nodes.append(b)
        if not [a,b] in edges: edges.append([a,b])
    return nodes, edges

def draw(nodes, edges):
    print("start to drawing ...")
    graph_obj = pyg.AGraph(directed=False, strict=False, ranksep=0.1, splines="spline", concentrate=True)
    graph_obj.add_nodes_from(nodes,color="#ffffff", fontname="times bold italic") 
    graph_obj.add_edges_from(edges)
    graph_obj.layout(prog='fdp')
    graph_obj.draw('service_graph.png')
    print("Done!")

if __name__ == '__main__':
    nodes, edges = nodes_edges(read("./data/relation_data.csv"))
    draw(nodes, edges)

# dot 
# 一个用来将生成的图形转换成多种输出格式的命令行工具。其输出格式包括PostScript,PDF,SVG,PNG,含注解的文本等等。
# neato 
# 用于sprint model的生成(在Mac OS版本中称为energy minimized)。
# twopi 
# 用于放射状图形的生成
# circo 
# 用于圆形图形的生成。
# fdp 
# 另一个用于生成无向图的工具。
# dotty 
# 一个用于可视化与修改图形的图形用户界面程序
部分结果约1/2
部分结果约1/2

参考 如何去阅读并学习一些优秀的开源框架的源码?

参考 Python - 运行流程图, call graph, 调用图

在断点后通过调用过程打出图像

代码语言:python
复制
#!/usr/bin/python
import sys, tempfile, webbrowser, pygraphviz as pgv

def draw_by_breakpoint(frame=None, slient=False):
    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

if __name__ == '__main__': draw_by_breakpoint()

call self method
call self method

在自己的django程序views里引入 from APPXXX.graph import draw_by_breakpoint

并且调用一下 draw_by_breakpoint

django+DRF-views (model-create)的调用关系图
django+DRF-views (model-create)的调用关系图

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
命令行工具
腾讯云命令行工具 TCCLI 是管理腾讯云资源的统一工具。使用腾讯云命令行工具,您可以快速调用腾讯云 API 来管理您的腾讯云资源。此外,您还可以基于腾讯云的命令行工具来做自动化和脚本处理,以更多样的方式进行组合和重用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档