代码def append_MySQL代码学习第七——jupyter notebook展示

7c68e643e5c48716234d33790b7effbd.png

jupyter notebook可以一方面用来验证自己的数据分析想法,一方面可以用来向别人展示自己的分析结果。

刚开始用,所以不好给jupyter notebook下个完整的定义。目前的用法就是在上面执行和调试用来展示gdb跟踪数据的python代码。用pyecharts画出图来。

先是下载和安装了Anaconda。Anaconda包含了完整的jupyter notebook以及python环境,还有其他的一些我目前没用到的强大的数据分析方面的工具。

Anaconda支持多个平台,我在windows和linux上都安装成功了。

在windows环境下,还需要安装pyecharts。打开Anaconda Prompt或者Anaconda Powershell Prompt,这是两个命令行的环境。

安装pyecharts:

python.exe -m pip install pyecharts

之后需要升级的话,则:

python.exe -m pip install --upgrade pyecharts

在linux环境下还可以直接用pip命令,但是window环境下直接用pip.exe的话,在我的环境中没有任何提示,但是貌似也能安装成功,不太清楚是怎么回事。

安装好以后就可以启动jupyter notebook了。

可以先启动Anaconda Nivagator,在其中再启动jupyter notebook。

也可以直接启动jupyter notebook。windows有对应的jupyter notebook启动菜单,linux中有同名的命令。

启动后就可以建目录,建脚本了。

这是代码和数据所在目录

e03eea68a0be6dcd5c7d09ee8597ef28.png

那个.ipynb就是jupyter notebook的文件,保存了有格式的展示页面,包括代码和展示内容。打开看一下:

6665c7611422de9b2d7bb2e99fd65864.png

下面是全部代码,小学时候写作文就喜欢写流水账,发现写代码的时候也容易写成流水账。

不过流水账要是不太长的话,应该是容易理解的。

# -*- coding: UTF-8 -*-
import json
from pyecharts import options as opts
from pyecharts.charts import Graph, Page
from pyecharts.charts import Bar, Grid, Line,Scatter
class GdbGraph(object):
    
    #初始化,从json格式的文件中读出所有节点和连接数据
    #文件中每行数据是一次断点收集的数据
    def __init__(self,nodesfile,linksfile,cmdsfile):
        self.__allnodes = []
        with open(nodesfile,"r") as nodesjf:
            for line in nodesjf.readlines():
                self.__allnodes.append(json.loads(line))
        self.__alllinks = []
        with open(linksfile,"r") as linksjf:
            for line in linksjf.readlines():
                self.__alllinks.append(json.loads(line))
        self.__allcmds = []
        with open(cmdsfile,"r") as cmdsjf:
            for line in cmdsjf.readlines():
                self.__allcmds.append(json.loads(line))
        self.__graph = Graph()
    
    #按入度数查找分割位置
    #nodes_for_indegree是需要计算入度数的节点列表
    def __getStop(self,nodes_for_indegree,start,breaks,max_indegrees):
        indegrees = {}
        #print(nodes_for_indegree)
        #入度数清零
        for n in nodes_for_indegree:
            indegrees[n] = 0
        stop = start
        links = []
        #查找分割位置
        stop_found = False
        for i in range(start,breaks):
            for l in self.__alllinks[i]:
                #要去掉重复的连接,两次断点之间的调用栈有很多是重复的,不能重复计算入度数
                if(l not in links):
                    links.append(l)
                    if(l["target"] in indegrees.keys()):
                        indegrees[l["target"]] += 1
                        if( indegrees[l["target"]] > max_indegrees ):
                            stop_found = True
                            stop = i
                            #print(start,stop)
                            #print(l["source"],l["target"])
                            break
            if(stop_found):
                break
        return stop

    #按照入度数分割成多个图,比如在同一个图中,函数A被2个不同的函数调用,则节点A的入度数是2
    #入度数越高,图就越复杂,不直观了
    #目前只计算断点所在函数被调用的次数
    def divdeGraph(self,max_indegrees=1):
        breaks = len(self.__alllinks)
        nodes_for_indegree = []
        #按函数名字来建立一个用来记录入度数的字典
        for nodes in self.__allnodes:
            #只统计断点触发所在函数的入度数
            n = nodes[0]["name"]
            if( n not in nodes_for_indegree):
                nodes_for_indegree.append(n)
        #print(indegrees)
        #用来保存分割以后的每段数据的开始位置
        start_pos = []
        start = 0
        #用loops变量避免死循环
        loops = 0
        while( start < breaks and loops < 200 ):
            loops +=1
            stop = start
            #如果命令行有输出,也要进行分割,用来指明当前断点有输出了
            #start > 0是避开第一行,一开始肯定是有命令行输入的,不是断点造成的
            if( start > 0 and len(self.__allcmds[start]) > 0 ):
                stop = start
            else:
                stop = self.__getStop(nodes_for_indegree,start,breaks,max_indegrees)

            #记录当前分割的开始位置
            start_pos.append(start)
            
            #一个断点就可能出现一个函数被调用多次的情况,要避免死循环
            #在仅统计断点所在函数的入度数时不会出现这种情况
            if(start==stop):
                stop += 1
            #下一个分割的开始位置
            start = stop
        return start_pos

    def getGraph( self,start=0,count=0 ) -> Graph:
        nodes = []
        links = []
        nodeobjs = []
        linkobjs = []
        if(count==0 or start+count > len(self.__alllinks)):
            count = len(self.__alllinks) - start
        #去掉重复的点和边
        for i in range(start,start+count):
            for n in self.__allnodes[i]:
                if(n not in nodes):
                    nodes.append(n)
                    #断点节点尺寸加大
                    if(n==self.__allnodes[i][0]):
                        ssize = 20
                    else:
                        ssize = 10
                    node = opts.GraphNode(name=n["name"],symbol_size=ssize)
                    nodeobjs.append(node)
            for l in self.__alllinks[i]:
                if(l not in links):
                    links.append(l)
        for l in links:
            linestyle = opts.LineStyleOpts(curve=0.2,width=2)
            link = opts.GraphLink( source=l["source"], target=l["target"], linestyle_opts=linestyle )
            linkobjs.append(link)
        subtitle = ""
        for line in self.__allcmds[start:start+count]:
            subtitle += "".join(line)
        c = (
            self.__graph
            #.add("", nodes, links, repulsion=2000, edge_symbol=["","arrow"] ,gravity=1)
            .add("", nodeobjs, linkobjs, repulsion=2000, edge_symbol=["","arrow"] ,gravity=4)
            .set_global_opts(title_opts=opts.TitleOpts(title="mysqld gdb 断点触发序号" + str(start) + "(鼠标滚轮放大缩小;左键拖拽移动图形)",subtitle=subtitle))
            #.set_global_opts(title_opts=opts.TitleOpts(title="mysqld gdb 断点触发序号" + str(start) + "(鼠标滚轮放大缩小;左键拖拽移动图形)nnSELECT * FROM TTTnUPDATE aaa SETn"))
        )
        return c
    def getBreaksCount( self ):
        return len(self.__alllinks)

gdb = GdbGraph("nodes.json","links.json","mysql_diff.json")
print("断点触发次数:",gdb.getBreaksCount())
bigpage=Page(interval = 20)
graph_start = gdb.divdeGraph(1)
length = len(graph_start)
for i in range(length):
    start = graph_start[i]
    count = gdb.getBreaksCount() - start
    if(i<length-1):
        count = graph_start[i+1] - start
    bigpage.add(GdbGraph("nodes.json","links.json","mysql_diff.json").getGraph(start,count))
print(" ( ´´ิ∀´ิ` )   鼠标单击输出的左侧部分,可以展开或者收缩整个输出   ( ´´ิ∀´ิ` ) ")
bigpage.render_notebook()

本例中,一共生成了15张图。切分的规则是断点(break point)所在函数节点的入度最多是1。也就是说不同函数对同一断点所在函数的调用会分在不同的图里。

之前还尝试了一下,所有节点的入度都要最多是1,那样会切分出更多的图。

还把mysql客户端的输入输出与同一时刻的断点信息放在一个图里。目的是为了看到,比如哪一个断点出现的时候客户端有返回信息了,那个命令发起的时候,触发了哪些断点。

上几个图

5adecaf255e0658d82edda3b4a03aebe.png

上图中从浅灰色的字能看到,是执行了update以后触发了断点。两个大圆点,就是设置了断点的函数,可以放大看一下。

07024d1ca962f90db71e35be31cc3dc4.png

不但可以放大缩小和移动,鼠标放到节点上,就只显示该节点以及与其连接的节点。

5b12f267e7e6434f2198f80afe9571a6.png

再截一个简单的图

6f46d37c076774bdd5fc84f2dd01dd7b.png

再找一个客户端得到反馈的图

43eb55ff6f3b04ade02e9c927c5055b5.png

断点停在这里的时候,客户端得到返回信息了。

先写到这。

我们ACMUG北京5月25日的活动马上就开始了,快报名吧,每次活动我都是希望仔细学习一下的,然而又无法只顾自己听课。

【北京】数据库热点话题公开研讨会-信通院专场​www.huodongxing.com
fef8e71b1cca7dce0948af16594cdac7.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值