How to Export Trees to GraphViz DOT Format with treelib

The Tree.to_graphviz() method in treelib generates standard GraphViz DOT syntax by traversing the tree structure and writing node definitions and edge connections to a file or stdout.

The treelib library provides a pure Python implementation for creating and manipulating tree data structures. When you need to visualize these trees, the library offers built-in support for GraphViz DOT export through a single method call that handles the entire conversion process.

Understanding the to_graphviz Method

The core implementation resides in [treelib/tree.py](https://github.com/caesar0301/treelib/blob/master/treelib/tree.py), specifically within the Tree class. The to_graphviz method walks your tree using Tree.expand_tree in width-first mode, collecting node identifiers and parent-child relationships to construct valid DOT language syntax.

Method Signature and Parameters

According to the source code in treelib/tree.py, the method signature is:

tree.to_graphviz(filename=None, shape="circle", graph="digraph", 
                 filter=None, key=None, reverse=False, sorting=True)
  • filename: Path to write the DOT file. If None, outputs to stdout via io.StringIO.
  • shape: GraphViz node shape. Defaults to "circle", but accepts any valid shape like "box" or "ellipse".
  • graph: Graph type. Use "digraph" for directed graphs (->) or "graph" for undirected (--).
  • filter, key, reverse, sorting: Control which nodes are included and their traversal order, passed directly to expand_tree.

How the DOT Source is Built

The method constructs two internal lists during traversal:

  1. nodes: Contains DOT node statements in the format "{id}" [label="{escaped_tag}", shape={shape}]
  2. connections: Contains edge statements linking children to parents

The final output assembles these into a complete DOT graph structure with proper UTF-8 encoding.

Exporting Trees to DOT Files

Writing to a File

To persist the DOT representation to disk, provide a filename parameter. The method opens the file with UTF-8 encoding and writes the complete graph definition:

from treelib import Tree
import tempfile

tree = Tree()
tree.create_node("Root", "root")
tree.create_node("Child 1", "child1", parent="root")
tree.create_node("Child 2", "child2", parent="root")

with tempfile.NamedTemporaryFile(mode="w", suffix=".dot", delete=False) as tmp:
    dot_path = tmp.name

tree.to_graphviz(filename=dot_path, shape="box")
print(f"DOT file written to {dot_path}")

Printing to Standard Output

When visualizing interactively or piping to other tools, omit the filename to print the DOT source directly to stdout:

tree.to_graphviz(shape="ellipse", graph="digraph")

This writes to an in-memory StringIO buffer and prints the result, allowing you to capture the output or pipe it directly to GraphViz commands.

Customizing the Graph Output

Changing Node Shapes

The shape parameter accepts any valid GraphViz node shape. Common options include "circle" (default), "box", "ellipse", "diamond", and "record". For example, to create a rectangular tree diagram:

tree.to_graphviz(filename="hierarchy.dot", shape="box")

Directed vs Undirected Graphs

By default, to_graphviz generates a directed graph using the digraph keyword and -> edge operators. To create an undirected graph where connections have no inherent directionality:

tree.to_graphviz(filename="undirected.dot", graph="graph")

This changes the DOT syntax to use the graph keyword and -- operators between nodes.

Complete Working Example

The repository provides a comprehensive example in [examples/save_tree2file.py](https://github.com/caesar0301/treelib/blob/master/examples/save_tree2file.py) that demonstrates building a sample tree and exporting it. Here is a standalone version:

from treelib import Tree

# Create a sample file system tree

tree = Tree()
tree.create_node("root", "root")  # root node

tree.create_node("etc", "etc", parent="root")
tree.create_node("usr", "usr", parent="root")
tree.create_node("bin", "bin", parent="usr")
tree.create_node("local", "local", parent="usr")

# Export to DOT format

tree.to_graphviz(filename="filesystem.dot", shape="folder", graph="digraph")

# Read and display the output

with open("filesystem.dot", "r", encoding="utf-8") as f:
    print(f.read())

This generates a valid DOT file where each node uses the "folder" shape (if supported by your GraphViz version) and edges point from parent to child directories.

Converting DOT to Images with GraphViz Tools

Once you have the DOT file, use the standard GraphViz command-line tools to render it into visual formats. The DOT format is plain text, making it compatible with all GraphViz layout engines:


# Convert to SVG (scalable vector graphics)

dot -Tsvg filesystem.dot -o filesystem.svg

# Convert to PNG (raster image)

dot -Tpng filesystem.dot -o filesystem.png

# Convert to PDF

dot -Tpdf filesystem.dot -o filesystem.pdf

# Use alternative layout engines

neato -Tpng filesystem.dot -o neato_layout.png

The unit tests in [tests/test_tree.py](https://github.com/caesar0301/treelib/blob/master/tests/test_tree.py) verify that to_graphviz produces syntactically valid DOT output that these tools can parse without errors.

Summary

  • Tree.to_graphviz() in treelib/tree.py is the primary interface for GraphViz DOT export, handling both file output and stdout printing.
  • The method performs a width-first traversal via expand_tree, escaping node tags and building proper DOT node and edge statements.
  • You control visual appearance through the shape parameter (default "circle") and graph structure through the graph parameter ("digraph" vs "graph").
  • Output files are written with UTF-8 encoding, ensuring compatibility with international characters in node identifiers and labels.
  • Generated DOT files work immediately with standard GraphViz tools like dot, neato, and sfdp to produce PNG, SVG, or PDF visualizations.

Frequently Asked Questions

What file format does treelib generate for GraphViz?

treelib generates plain text files conforming to the DOT graph description language, which is the native input format for all GraphViz tools. The output uses standard DOT syntax with node definitions and edge connections, saved with UTF-8 encoding whether writing to a file or stdout.

Can I customize node shapes in the DOT export?

Yes. The shape parameter in to_graphviz accepts any valid GraphViz shape string. While the default is "circle", you can pass "box", "ellipse", "diamond", or other supported shapes to change how nodes appear in the final rendered graph.

Does to_graphviz support filtering specific nodes?

Yes. The method accepts filter, key, reverse, and sorting parameters that are passed directly to Tree.expand_tree. This allows you to export only subtrees, sort nodes before export, or reverse the traversal order to control which nodes appear in the DOT output.

How do I convert the generated DOT file to PNG or SVG?

Use the GraphViz command-line tools after exporting. Run dot -Tpng input.dot -o output.png for PNG images or dot -Tsvg input.dot -o output.svg for scalable vector graphics. The DOT file produced by treelib is fully compatible with the dot, neato, fdp, and other GraphViz layout engines.

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 →