【Python】可视化Python库的依赖关系

主要用了两个库:pipdeptree和pyecharts。

pipdeptree用来解析所有库的依赖关系。

pyecharts用来显示依赖的网络关系。

通常的方法应该是通过输入下面命令:

pipdeptree --json-tree > pkg.json

得到关系树文件,然后解析该文件并在pyecharts显示即可。

不过我不想解析json文件了。

这里是直接输入pipdeptree命令,得到控制台输出,然后解析字符串来做的,比较暴力。

ubuntu22.04系统(不同系统好像不一样)控制台输出为下面这种格式:

apturl==0.5.2
autopep8==2.0.2
├── pycodestyle [required: >=2.10.0, installed: 2.10.0]
└── tomli [required: Any, installed: 2.0.1]
bcrypt==3.2.0
blendmodes==2022
├── aenum [required: >=3.1.7,<4, installed: 3.1.12]
├── deprecation [required: >=2.1.0,<3, installed: 2.1.0]
│   └── packaging [required: Any, installed: 23.0]
├── numpy [required: >=1.22.1,<2, installed: 1.24.1]
└── Pillow [required: >=9.0.0,<10, installed: 9.0.1]

发现根据字符串中的""字符和该字符所在的位置,就能知道该库是根节点还是被第几层依赖的节点。

然后需要确定前后库的依赖连接,确定的方法也比较暴力,最后转为pyecharts输出即可。

代码如下:

from pyecharts.charts import Graph
from pyecharts import options as opts
import subprocess

# 调用系统命令并获取结果 pip install pipdeptree
result = subprocess.run('pipdeptree', capture_output=True, text=True)
output = result.stdout
output = output.split('\n')

depIndex = []
depName = []

for v in output:
    num = v.find('──')
    if num==-1:
        depIndex.append(0)
        name = v.split('==')
        depName.append(name[0])
    else:
        depIndex.append(num//4+1)
        name = v.split('──')
        name = name[1].split(' ')
        depName.append(name[1])

depIndex.pop()
depName.pop()
maxId = max(depIndex)

nodeNames =list(set(depName))

dicts={}
for nodeName in nodeNames:
    dicts[nodeName] = 5

links = []
while maxId!=0: 
    findMax = False  
    for i in range(len(depIndex)):
        if i!=0:
            if depIndex[i]==maxId:
                link = {"source":depName[i-1],"target":depName[i]}
                
                if link not in links:
                    dicts[depName[i]] = dicts[depName[i]] + 2

                links.append(link)
                depIndex.pop(i)
                depName.pop(i)
                findMax = True
                break
    if findMax==False:
        maxId= maxId-1

nodes = []
for nodeName in nodeNames:
    node = {"name":nodeName,"symbolSize":dicts[nodeName]}
    nodes.append(node)

graph = Graph(init_opts=opts.InitOpts(width="1920px", height="1080px"))
graph.add("", nodes, links)
graph.render('show.html')

所有连接效果如下,球越大代表被依赖的越多:

局部效果如下,选中节点后相关节点高亮:

posted @ 2024-03-24 21:34  Dsp Tian  阅读(13)  评论(0编辑  收藏  举报