我知道debtree可以为给定的包生成依赖关系图,如下所示:
sudo apt-get install debtree
sudo apt-get install graphviz
debtree alsa-base > alsa-base.dot
dot -T png -o alsa-base.png alsa-base.dot
但是如果我想要整个系统的依赖图,并且每个包只显示一次,该怎么办?
答案1
这是使用 Python 实现此操作的一种巧妙方法。
首先将所有已安装的包写入一个文件。
apt list --installed > installed_packages.txt
遍历该列表并使用debtree获取每个包的一阶依赖关系。如果您有很多包(主要是lib*),这可能需要相当长的时间。
此脚本最好在 Jupyter Lab 等交互式环境中运行。它会缓存所有工作edges_dict
,如果已经有条目,则会跳过检索过程。
import json
import subprocess
from io import StringIO
import pydot
import networkx as nx
names = [package.split("/")[0] for package in open("installed_packages.txt").read().split("\n")[1:-1]]
edges_dict = dict()
command = "debtree --with-suggests --max-depth 1 {}"
for name in names:
if name not in edges_dict.keys():
try:
process = subprocess.Popen(command.format(name).split(), stdout=subprocess.PIPE)
output, error = process.communicate()
if error is None:
g = nx.drawing.nx_pydot.read_dot(StringIO(output.decode()))
edges_dict[name] = list(g.edges())
else:
print(name, error)
except:
print(name, "Failed")
json.dump(edges_dict, open("edges.json", "w"))
edges_dict = json.load(open("edges.json"))
利用这些数据,您可以使用 networkx 创建图表......
import networkx as nx
g = nx.DiGraph()
for name, edges in edges_dict.items():
g.add_edges_from(edges)
或者带有 pandas 的 DataFrame。
data = list()
for name, edges in edges_dict.items():
for node1, node2 in edges:
data.append([name, node1, node2])
df = pd.DataFrame(data, columns=["name", "package", "dependency"])
# many packages have themself as a dependency
df = df[df["package"] != df["dependency"]]
希望对您有帮助:)