How to Create a New Tree in treelib: A Complete Guide

Create a new tree in treelib by instantiating the Tree class, then call create_node() to establish a root without a parent parameter, and attach children by specifying their parent identifiers.

The treelib library provides a pure Python implementation for managing hierarchical tree structures. Whether you need to model organizational charts, file systems, or decision trees, understanding how to properly initialize and populate a Tree object is essential. This guide walks through the exact implementation details found in the caesar0301/treelib repository.

Core Architecture of treelib

The Tree Container

The Tree class serves as the primary container that manages all nodes, tracks the root identifier, and provides traversal and manipulation APIs. According to the source code in treelib/tree.py (lines 82-101), the Tree class initializes with an internal node dictionary and optional identifier.

The Node Building Blocks

Each element in the hierarchy is represented by the Node class, defined in treelib/node.py (lines 47-60). Nodes store tags, unique identifiers, optional data payloads, and maintain parent/children relationships.

Instantiating an Empty Tree

To create a new tree in treelib, start by calling the Tree constructor with no arguments:

from treelib import Tree

tree = Tree()

The Tree.__init__ method (lines 69-101 in treelib/tree.py) creates an internal node dictionary (self._nodes), generates a unique tree identifier, and prepares a placeholder for the root node. You can optionally pass a node_class parameter to use custom node implementations, provided they subclass Node.

Adding the Root Node

The first node added to a tree becomes the root. You must call create_node without specifying a parent parameter:

tree.create_node(tag="Root", identifier="root")

According to the implementation in treelib/tree.py (lines 825-876), the create_node method validates that the tree is empty before allowing a root creation. If you attempt to create a second root without a parent, the library raises a MultipleRootError (documented in the method docstring at lines 49-52).

Building the Hierarchy with Child Nodes

Once the root exists, attach child nodes by specifying the parent parameter with the identifier of the existing node:

tree.create_node(tag="Child A", identifier="child_a", parent="root")
tree.create_node(tag="Child B", identifier="child_b", parent="root")

The create_node method processes the parent parameter through the internal add_node logic. If the specified parent identifier does not exist in self._nodes, the library raises a NodeIDAbsentError (see docstring lines 44-53 in treelib/tree.py). The tree maintains an O(1) lookup table for fast parent validation and node retrieval.

Complete Working Example

The repository's examples/getting_started.py (lines 22-36) demonstrates the complete workflow:

from treelib import Tree

def lesson_1_creating_trees():
    tree = Tree()
    tree.create_node("Root", "root")
    tree.show()
    
    # Add children

    tree.create_node("Child1", "child1", parent="root")
    tree.create_node("Child2", "child2", parent="root")
    tree.show()

if __name__ == "__main__":
    lesson_1_creating_trees()

Running this script produces:


Root
├── Child1
└── Child2

Advanced Tree Creation Techniques

Using Custom Node Classes

You can extend the Node class to add custom attributes:

from treelib import Tree, Node

class MyNode(Node):
    def __init__(self, tag, identifier=None):
        super().__init__(tag, identifier)
        self.custom_attr = "extra"

tree = Tree(node_class=MyNode)
tree.create_node("Root", "root")
print(tree["root"].custom_attr)  # Output: extra

The Tree constructor validates that custom node classes subclass Node (lines 22-24 in treelib/tree.py).

Building from Dictionary Data

Convert nested dictionaries to trees recursively:

import uuid
from treelib import Tree

def dict_to_tree(d, parent_id=None, tree=None):
    if tree is None:
        tree = Tree()
    for key, value in d.items():
        node_id = str(uuid.uuid4())
        tree.create_node(tag=key, identifier=node_id, parent=parent_id)
        if isinstance(value, dict):
            dict_to_tree(value, parent_id=node_id, tree=tree)
    return tree

sample = {"A": {"B": {}, "C": {"D": {}}}}
my_tree = dict_to_tree(sample)
my_tree.show()

Summary

  • Instantiate a new tree with Tree() from treelib/tree.py.
  • Create the root by calling create_node() without a parent parameter; this triggers the root assignment logic in lines 825-876.
  • Add children by specifying the parent identifier in subsequent create_node() calls.
  • Validate that parent identifiers exist to avoid NodeIDAbsentError, and avoid creating multiple roots to prevent MultipleRootError.
  • Customize node behavior by passing a node_class subclass to the Tree constructor.

Frequently Asked Questions

What happens if I try to create a second root node?

If you call create_node() without a parent parameter on a tree that already contains a root, the library raises a MultipleRootError. According to the source code in treelib/tree.py (lines 49-52), the tree strictly enforces a single-root hierarchy unless you explicitly create a new Tree instance.

Can I use custom identifiers instead of auto-generated UUIDs?

Yes. The identifier parameter in create_node() accepts any hashable value, including strings, integers, or UUIDs. The implementation in treelib/tree.py (lines 825-876) stores these identifiers in the internal self._nodes dictionary, requiring only that they remain unique within the tree.

How do I check if a tree is empty before adding the root?

You can verify that a tree has no nodes by checking len(tree) or accessing the tree.root property. An empty tree returns None for tree.root and has a length of zero. The Tree.__init__ method in treelib/tree.py (lines 69-101) initializes these empty states before any nodes are added.

Is treelib thread-safe for concurrent tree creation?

The treelib library does not implement internal locking mechanisms. While creating separate Tree instances in different threads is safe, concurrently modifying a single Tree instance from multiple threads requires external synchronization. The source code in treelib/tree.py uses standard Python dictionaries for node storage, which are not thread-safe for concurrent writes.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →