pythonanytree

How do I find a specific Python anytree descendant?


The following Python anytree construction

top = Node("top")
a = Node("a", parent=top)
b = Node("b", parent=top)
c = Node("c", parent=a)
d = Node("d", parent=a)
e1 = Node("e", parent=c)
e2 = Node("e", parent=a)
c1 = Node("c", parent=b)
e3 = Node("e", parent=c1)
print(RenderTree(top, style=AsciiStyle()).by_attr())

produces this tree:

top
|-- a
|   |-- c
|   |   +-- e
|   |-- d
|   +-- e
+-- b
    +-- c
        +-- e

I want to process node a/c/e under top if that node exists. If it doesn't exist, I want to get None.

Here is what I have implemented that does what I want:

gnode = anytree.search.find(top, lambda node : str(node)=="Node('/top/a/c/e')")
print(f"Exp match, rcv {gnode}")

gnode = anytree.search.find(top, lambda node : str(node)=="Node('/top/a/c/f')")
print(f"Exp None, rcv {gnode}")

The above code returns the following:

Exp match, rcv Node('/top/a/c/e')
Exp None, rcv None

Although the code works, I'm thinking there must be a better way to do it -- something like top.get_descendant("a/c/e") that would directly access that node instead of searching for it.

What's the right way to access node a/c/e under node top (and get None if it doesn't exist)?


Solution

  • Reading through the docs it looks like you want the anytree.resolver module:

    import sys
    import anytree
    
    top = anytree.Node("top")
    a = anytree.Node("a", parent=top)
    b = anytree.Node("b", parent=top)
    c = anytree.Node("c", parent=a)
    d = anytree.Node("d", parent=a)
    e1 = anytree.Node("e", parent=c)
    e2 = anytree.Node("e", parent=a)
    c1 = anytree.Node("c", parent=b)
    e3 = anytree.Node("e", parent=c1)
    
    r = anytree.resolver.Resolver()
    
    for path in sys.argv[1:]:
        try:
            node = r.get(top, path)
            print(f"path {path} exists: {node}")
        except anytree.resolver.ChildResolverError:
            print(f"path {path} does not exist")
    

    Testing the above code with a path that exists:

    $ python nodes.py /top/a/c/e
    path /top/a/c/e exists: Node('/top/a/c/e')
    

    And with a path that does not exist:

    $ python nodes.py /top/a/e/c
    path /top/a/e/c does not exist