依赖树实现

发布于 2024-10-22 02:29:51 字数 279 浏览 3 评论 0原文

对于那些使用 apt-get 的人来说,您知道每次安装/卸载某些东西时,您都会收到通知说您需要/不再需要某些依赖项。

我正在尝试理解其背后的理论,并可能实现我自己的版本。我做了一些谷歌搜索,想出了大部分耦合的东西。据我了解,耦合是两个相互依赖的类/模块。这不正是我正在寻找的。我正在寻找的更像是依赖关系树生成,我可以在其中找到最不依赖的模块(我已经采用了递归方式来执行此操作),并且(这是我尚未完成的部分)找到什么删除节点后不再需要。

另外,学习图论会有帮助吗?有没有关于最好使用 Python 作为语言的教程?

For those who used apt-get, you know that everytime you install / uninstall something, you get the notificatons saying you need / no longer need certain dependencies.

I'm trying to understand the theory behinds this and potentially implement my own version of this. I've done some googling, came up with mostly coupling stuff. From what I understand, coupling is 2 classes/modules that depends on each other. This is not exactly what I'm looking for. What I'm looking for is more like a dependencies tree generation, where I can find the least dependent module (I've already made a recursive way of doing this), and (this being the part i haven't done) finding what's no longer needed after removing a node.

Also, would learning about graph theory help? And is there any tutorials on that preferably using Python as a language?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

念﹏祤嫣 2024-10-29 02:29:51

可能会引起一些兴趣:

def dep(arg):
    '''
        Dependency resolver

    "arg" is a dependency dictionary in which
    the values are the dependencies of their respective keys.
    '''
    d=dict((k, set(arg[k])) for k in arg)
    r=[]
    while d:
        # values not in keys (items without dep)
        t=set(i for v in d.values() for i in v)-set(d.keys())
        # and keys without value (items without dep)
        t.update(k for k, v in d.items() if not v)
        # can be done right away
        r.append(t)
        # and cleaned up
        d=dict(((k, v-t) for k, v in d.items() if v))
    return r

if __name__=='__main__':
    d=dict(
        a=('b','c'),
        b=('c','d'),
        e=(),
        f=('c','e'),
        g=('h','f'),
        i=('f',)
    )
    print dep(d)

This might be of some interest:

def dep(arg):
    '''
        Dependency resolver

    "arg" is a dependency dictionary in which
    the values are the dependencies of their respective keys.
    '''
    d=dict((k, set(arg[k])) for k in arg)
    r=[]
    while d:
        # values not in keys (items without dep)
        t=set(i for v in d.values() for i in v)-set(d.keys())
        # and keys without value (items without dep)
        t.update(k for k, v in d.items() if not v)
        # can be done right away
        r.append(t)
        # and cleaned up
        d=dict(((k, v-t) for k, v in d.items() if v))
    return r

if __name__=='__main__':
    d=dict(
        a=('b','c'),
        b=('c','d'),
        e=(),
        f=('c','e'),
        g=('h','f'),
        i=('f',)
    )
    print dep(d)
暗藏城府 2024-10-29 02:29:51

图论是一条出路。

图只是一堆地方(顶点),它们之间有道路(边),特别是我们谈论的是有向图,这意味着单向道路。基本上,找出依赖关系意味着找出沿着单向道路可以到达特定城镇的所有地点。

所以现在,你已经有了一堆模块,它们成为你的顶点。假设我们有 A 和 B,并且我们知道 B 依赖于 A,因此存在从 A 到 B 的有向边——一条“单向路”。

如果 C 依赖于 B,则有 A→B→C 。

形式上,图只是顶点和(有序)顶点对(称为边)的集合。您想要一种称为“拓扑排序”的图形算法,现在您需要阅读一些内容。

Graph theory is the way to go.

A graph is just a bunch of places (vertices) with roads (edges) between them, and in particular we're talking about a directed graph, which means one-way roads. Figuring out dependencies means, basically, finding out all the places that can reach a particular town along the one-way roads.

So now, you've got you bunch of modules, which become your vertices. Let's say we have A and B, and we know B depends on A, so there's a directed edge -- a "one way road" -- from A to B.

If C depends on B, then you have A→B→C.

Formally, a graph is just a collection of vertices and (ordered) pairs of vertices, called the edges. You want an graph algorithm called "topological sort", and now you've got some stuff to read.

浅唱ヾ落雨殇 2024-10-29 02:29:51

我确实编写了一个工具,用于查找和绘制 PyPi 上的 Python 包之间的依赖关系。这是 贪吃

我确实用来分析我正在使用的一些库的依赖关系。以下是一些图表:

在此处输入图像描述
在此处输入图像描述

我不确定这是否是您想要的。如果是,您可以在此处阅读源代码,它是一个开源项目。更多依赖关系图可以查看图库

讲一下我是如何实现的为了查找包依赖项,我使用 pip 作为后端。为了绘制图表,我使用 Networkx

I did wrote a tool for finding and drawing the dependencies between Python packages on PyPi. It's gluttony

And I did use to analysis the dependencies of some library I'm using. Here are some of diagrams:

enter image description here
enter image description here

I'm not sure is this what you want. If it is, you can read the source code here, it is an open source project. For more dependencies diagrams, you can view the gallery

Talking about how I implement it, for finding package dependencies, I use pip as backend. For drawing diagrams, I use Networkx.

别忘他 2024-10-29 02:29:51

这是我的工具,可以满足您的要求:

https://github.com/bedbad/pyimports

您可以使用文件和基本数据结构的 .ast 来创建任何您喜欢的树:

def get_imports(path):
imports = dict()
with open(path) as fh:
    root = ast.parse(fh.read(), path)
    for node in ast.iter_child_nodes(root):
        if isinstance(node, ast.Import):
            temp = imports
            for n in node.names:
                namelist = n.name.split('.')
                if len(namelist) > 1:
                    for st in namelist:
                        temp[st] = dict()
                        temp = temp[st]
                else:
                    temp[n.name] = dict()
        elif isinstance(node, ast.ImportFrom):
            temp = imports
            namelist = node.module.split('.')
            for n in namelist:
                temp[n] = dict()
                temp = temp[n]
            for n in node.names:
                temp[n.name] = dict()
        else:
            continue
return imports

请注意,Python 中的基本只是一个字典。尽管如此,据我所知,没有树 DS 实际上实现了对自循环的检查。那东西叫做Floyd-Warshall

Here's the tool of mine that does what you asked for:

https://github.com/bedbad/pyimports

You can any sort of tree you like using .ast of file and basic data structures:

def get_imports(path):
imports = dict()
with open(path) as fh:
    root = ast.parse(fh.read(), path)
    for node in ast.iter_child_nodes(root):
        if isinstance(node, ast.Import):
            temp = imports
            for n in node.names:
                namelist = n.name.split('.')
                if len(namelist) > 1:
                    for st in namelist:
                        temp[st] = dict()
                        temp = temp[st]
                else:
                    temp[n.name] = dict()
        elif isinstance(node, ast.ImportFrom):
            temp = imports
            namelist = node.module.split('.')
            for n in namelist:
                temp[n] = dict()
                temp = temp[n]
            for n in node.names:
                temp[n.name] = dict()
        else:
            continue
return imports

Notice the basic in Python is just a dict. Redardless of that no tree DS I know of Actually implements checks on self looping. That thing is called Floyd-Warshall

她如夕阳 2024-10-29 02:29:51
  1. 遍历旧的依赖树。构建其中所有元素的集合
  2. 遍历新的依赖树。和以前一样做。
  3. 从前者中减去后者set。结果就是你的答案。

或者:

  1. 遍历旧的依赖树。在每个节点上,存储依赖(指向)该节点的事物的数量。
  2. 删除您要删除的项目。遵循其所有依赖项并将其使用计数减 1。如果以这种方式递减会将节点的计数降低到 0,则不再需要。

前者实现起来比较简单,但效率较低。后者虽然高效,但实施起来比较困难。

  1. Walk the old dependency tree. Build a set of all of the elements in it.
  2. Walk the new dependency tree. Do the same as before.
  3. Subtract the latter set from the former. The result is your answer.

Alternatively:

  1. Walk the old dependency tree. At each node, store the number of things that depend on (point to) that node.
  2. Remove the item you're wanting to remove. Follow all of its dependencies and decrement their usage count by 1. If decrementing this way lowers the count for a node to 0, it is no longer necessary.

The former is simpler to implement, but less efficient. The latter is efficient, but harder to implement.

∞琼窗梦回ˉ 2024-10-29 02:29:51

我认为您正在寻找的步骤是区分已明确安装的软件包和依赖项。完成此操作后,您可以构建所有请求软件包的依赖关系树,并将这些软件包集与已安装软件包集进行比较。假设所有请求的包都已安装,对这些进行异或,应该会给出不再依赖的所有包的集合。

I think the step you're looking for is to differentiate between packages you has explicitly installed, and those that are dependencies. Once you have done this you can build dependency trees of all requested packages, and compare the set of these packages with the set of installed packages. XORing these, assuming all requested packages are installed, should give you the set of all packages which are no longer depended on.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文