pydot
Build, parse, and render Graphviz DOT graphs from pure Python.
Repository Health
Technical Analysis
pydot is a pure-Python interface to Graphviz’s DOT graph description language. It lets you construct directed and undirected graphs programmatically — adding nodes, edges, subgraphs, and clusters as native Python objects — then render them to any format Graphviz supports (PNG, SVG, PDF, PostScript, and dozens more) by shelling out to the locally installed Graphviz binaries.
Beyond generation, pydot can also parse existing DOT files or strings back into the same object model using a pyparsing-based grammar, making round-trips between DOT source and Python objects straightforward. It integrates directly with NetworkX’s nx_pydot module for converting between NetworkX graphs and pydot graphs, and is commonly used as the rendering backend behind higher-level graph-visualization tooling.
What You Get
- A typed object model (Dot, Graph, Subgraph, Cluster, Node, Edge) covering the full set of Graphviz graph/node/edge/cluster attributes
- Auto-generated write_<format>() and create_<format>() methods for every Graphviz output format (PNG, SVG, PDF, PostScript, GIF, and more)
- A pyparsing-based DOT parser (graph_from_dot_file / graph_from_dot_data) for round-tripping existing DOT source back into Python objects
- Direct interoperability with NetworkX via its nx_pydot conversion module
Common Use Cases
- Rendering dependency graphs, call graphs, or state machines generated from another tool’s output
- Visualizing NetworkX graphs by converting them to pydot and rendering with Graphviz
- Parsing and editing existing .dot files programmatically (e.g. relabeling nodes, recoloring edges) before re-rendering
- Generating architecture or data-lineage diagrams dynamically from application data
Under The Hood
Architecture
pydot has a flat, four-module layout: classes.py defines low-level container types (FrozenDict, AttributeDict, EdgeEndpoint); core.py defines the core object model (Common base class, Node, Edge, Graph, Subgraph, Cluster, Dot) plus a subprocess-based rendering pipeline (call_graphviz, Dot.create/write, and dynamically generated per-format write_*/create_* methods); dot_parser.py implements a pyparsing grammar that reconstructs those same objects from DOT text (graph_from_dot_data/graph_from_dot_file); and exceptions.py holds a small typed exception hierarchy. Data flows both ways — pydot objects serialize via to_string() to DOT syntax and are handed to the Graphviz binaries through subprocess.Popen, while the parser reverses that path from DOT source back into objects. Every class shares Common’s dict-based attribute storage (obj_dict), so that scheme is the one abstraction the whole object model depends on.
Tech Stack
A pure Python 3.9+ package with a single runtime dependency, pyparsing>=3.1.0, used for grammar-based DOT parsing. Rendering delegates to the external Graphviz binaries (dot, twopi, neato, circo, fdp, sfdp) invoked via subprocess.Popen, so Graphviz itself is a required system dependency rather than a Python package. Build tooling is setuptools (>=77) through pyproject.toml with a dynamically read version attribute; dev tooling covers ruff for linting, mypy --strict for typing, pytest/pytest-cov/pytest-xdist plus tox for testing, and zest.releaser for releases. A trimmed copy of CPython 3.12’s tempfile module is vendored to backport ignore_cleanup_errors support to older Python versions. CI runs the full matrix across Python 3.9–3.15 on Ubuntu, Windows, and macOS.
Code Quality
The test suite spans six files (test_api.py, test_classes.py, test_context_managers.py, test_logging.py, test_parser.py, test_pydot.py) covering the public API, parsing round-trips, context-manager behavior, and logging output, with coverage tracked via a dedicated coverage-comment CI badge. mypy runs in strict mode across the source tree, with consistent type hints, TYPE_CHECKING-gated imports, and Final/cast annotations throughout. Error handling is explicit rather than swallowed: a small typed exception hierarchy backs parser errors, and Dot.create() re-raises OSError with a clarified message when the Graphviz binary isn’t found. Style is enforced by ruff across an extensive rule set, and everything runs in CI on every push. This reads as a mature, well-governed codebase — typed, tested, linted, and cross-platform CI-gated.
API Design
The public surface is small and discoverable: Dot, Graph, Subgraph, Cluster, Node, and Edge, each accepting Graphviz attributes as keyword arguments and exposing add_node/add_edge/add_subgraph alongside auto-generated get_*/set_* accessors for every valid Graphviz attribute. Getting started requires little boilerplate — construct a Dot, add nodes and edges, and call write_png() or create_svg() without ever touching the underlying subprocess call directly, or go the other way with a one-line graph_from_dot_file(). Docstrings are unusually thorough for a library this size, covering platform-specific caveats in detail. The main friction point is that format-specific methods like write_png() are generated dynamically rather than declared explicitly, which can make them less visible to IDEs and type checkers without special-casing. The overall approach — attribute-dict object model plus subprocess-shelled rendering — is the standard pattern for a Graphviz Python binding rather than a novel one, but it’s executed cleanly.
Used by 2 apps in this directory
Rasa Open Source
AI Assistants · AI Development
Rasa Open Source is a Python machine learning framework for building contextual, multi-turn chatbots and voice assistants that understand natural language and maintain conversation state.
skrub
Developer Tools
Turn messy real-world dataframes into machine learning features — no manual wrangling required.