# How to Export Trees to GraphViz DOT Format with treelib

> Easily export your treelib trees to GraphViz DOT format using the to_graphviz() method. Generate DOT syntax for visualization and analysis.

- Repository: [Xiaming Chen/treelib](https://github.com/caesar0301/treelib)
- Tags: how-to-guide
- Published: 2026-02-26

---

**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/main/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`](https://github.com/caesar0301/treelib/blob/main/treelib/tree.py), the method signature is:

```python
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:

```python
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:

```python
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:

```python
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:

```python
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/main/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:

```python
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:

```bash

# 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/main/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`](https://github.com/caesar0301/treelib/blob/main/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.