Graphviz

Latest PyPI Version License Supported Python Versions Format Readthedocs

Travis Coveralls

This package facilitates the creation and rendering of graph descriptions in the DOT language of the Graphviz graph drawing software (repo) from Python.

Create a graph object, assemble the graph by adding nodes and edges, and retrieve its DOT source code string. Save the source code to a file and render it with the Graphviz installation of your system.

Use the view option/method to directly inspect the resulting (PDF, PNG, SVG, etc.) file with its default application. Graphs can also be rendered and displayed within Jupyter notebooks (a.k.a. IPython notebooks, example).

Installation

This package runs under Python 2.7, and 3.3+, use pip to install:

$ pip install graphviz

To render the generated DOT source code, you also need to install Graphviz (download page).

Make sure that the directory containing the dot executable is on your systems’ path.

Quickstart

Create a graph object:

>>> from graphviz import Digraph

>>> dot = Digraph(comment='The Round Table')

>>> dot  
<graphviz.dot.Digraph object at 0x...>

Add nodes and edges:

>>> dot.node('A', 'King Arthur')
>>> dot.node('B', 'Sir Bedevere the Wise')
>>> dot.node('L', 'Sir Lancelot the Brave')

>>> dot.edges(['AB', 'AL'])
>>> dot.edge('B', 'L', constraint='false')

Check the generated source code:

>>> print(dot.source)  
// The Round Table
digraph {
    A [label="King Arthur"]
    B [label="Sir Bedevere the Wise"]
    L [label="Sir Lancelot the Brave"]
        A -> B
        A -> L
        B -> L [constraint=false]
}

Save and render the source code, optionally view the result:

>>> dot.render('test-output/round-table.gv', view=True)  
'test-output/round-table.gv.pdf'
https://raw.github.com/xflr6/graphviz/master/docs/round-table.png

See also

License

This package is distributed under the MIT license.

User Guide

User Guide

Installation

graphviz provides a simple pure-Python interface for the Graphviz graph-drawing software. It runs under Python 2.7 and 3.3+. To install it with pip run the following:

$ pip install graphviz

For a system-wide install, this typically requires administrator access. For an isolated install, you can run the same inside a virtualenv or a venv (Python 3.3+ only).

The only dependency is a working installation of Graphviz (download page).

After installing Graphviz, make sure that its bin/ subdirectory containing the layout commands for rendering graph descriptions (dot, circo, neato, etc.) is on your systems’ path: On the command-line, dot -V should print the version of your Graphiz installation.

Basic usage

The graphviz module provides two classes: Graph and Digraph. They create graph descriptions in the DOT language for undirected and directed graphs respectively. They have the same API.

Create a graph by instantiating a new Graph or Digraph object:

>>> from graphviz import Digraph

>>> dot = Digraph(comment='The Round Table')

>>> dot  
<graphviz.dot.Digraph object at 0x...>

Their constructors allow to set the graph’s name, the filename for the DOT source and the rendered graph, a comment for the first source code line, etc.

Add nodes and edges to the graph object using its node() and edge() or edges() methods:

>>> dot.node('A', 'King Arthur')
>>> dot.node('B', 'Sir Bedevere the Wise')
>>> dot.node('L', 'Sir Lancelot the Brave')

>>> dot.edges(['AB', 'AL'])
>>> dot.edge('B', 'L', constraint='false')

The node()-method takes a name identifier as first argument and an optional label. The edge()-method takes the names of start- and end-node, while edges() takes iterable of name-pairs. Keyword arguments are turned into (node and edge) attributes (see Graphviz docs).

Check the generated source code:

>>> print(dot.source)  
// The Round Table
digraph {
    A [label="King Arthur"]
    B [label="Sir Bedevere the Wise"]
    L [label="Sir Lancelot the Brave"]
        A -> B
        A -> L
        B -> L [constraint=false]
}

Use the render()-method to save the source code and render it with the default layout program (dot, see below for using other layout commands).

>>> dot.render('test-output/round-table.gv', view=True)  
'test-output/round-table.gv.pdf'
_images/round-table.svg

Passing view=True will automatically open the resulting (PDF, PNG, SVG, etc.) file with your system’s default viewer application for the file type.

Formats

To use a different output file format than the default PDF, use the format argument when creating your Graph or Digraph object:

>>> from graphviz import Graph

>>> g = Graph(format='png')

You can also change the format attribute on an existing graph object:

>>> dot.format = 'svg'

>>> dot.render()  
'test-output/round-table.gv.svg'

Piped output

To directly access the results from the Graphviz rendering command (e.g. dot) as binary data string from within Python instead of writing to a file, use the pipe()-method of your Graph or Digraph object:

>>> h = Graph('hello', format='svg')

>>> h.edge('Hello', 'World')

>>> print(h.pipe().decode('utf-8'))  
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg
...
</svg>

Note that pipe() returns the raw stdout from the rendering command (str on Python 2, bytes on Python 3): When piping into plain-text formats like svg or plain, you usually want to decode the return value as shown above.

Note

The output for pipe() is buffered in memory, so do not use this method if the data size is large.

Jupyter notebooks

Graph and Digraph objects have a _repr_svg_()-method so they can be rendered and displayed directly inside a Jupyter notebook. For an example, check the examples/notebook.ipynb file in the source repository/distribution (nbviewer).

Styling

Use the graph_attr, node_attr, and edge_attr arguments to change the default appearance of your graph, nodes, and edges.

>>> ps = Digraph(name='pet-shop', node_attr={'shape': 'plaintext'})

>>> ps.node('parrot')
>>> ps.node('dead')
>>> ps.edge('parrot', 'dead')

After creation, they can be edited on the graph object:

>>> ps.graph_attr['rankdir'] = 'LR'
>>> ps.edge_attr.update(arrowhead='vee', arrowsize='2')

>>> print(ps.source)  
digraph "pet-shop" {
    graph [rankdir=LR]
    node [shape=plaintext]
    edge [arrowhead=vee arrowsize=2]
        parrot
        dead
            parrot -> dead
}
_images/pet-shop.svg

Attributes

To directly add attitbute statements (affecting all following graph, node, or edge items within the same (sub-)graph), use the attr()-method with the target as first argument:

>>> ni = Graph('ni')

>>> ni.attr('node', shape='rarrow')
>>> ni.node('1', 'Ni!')
>>> ni.node('2', 'Ni!')

>>> ni.node('3', 'Ni!', shape='egg')

>>> ni.attr('node', shape='star')
>>> ni.node('4', 'Ni!')
>>> ni.node('5', 'Ni!')

By omitting its first argument, you can use it to set arbitrary attributes as key-value pairs targeting the current (sub-)graph (e.g. for rankdir, label, or setting rank=same within a subgraph context):

>>> ni.attr(rankdir='LR')

>>> ni.edges(['12', '23', '34', '45'])
>>> print(ni.source)  
graph ni {
    node [shape=rarrow]
    1 [label="Ni!"]
    2 [label="Ni!"]
    3 [label="Ni!" shape=egg]
    node [shape=star]
    4 [label="Ni!"]
    5 [label="Ni!"]
    rankdir=LR
        1 -- 2
        2 -- 3
        3 -- 4
        4 -- 5
}
_images/ni.svg

Subgraphs & clusters

Graph and Digraph objects have a subgraph()-method for adding a subgraph to an instance.

There are two ways to use it: Either with a ready-made graph object of the same kind as the only argument (whose content is added as a subgraph) or omitting the graph argument (returning a context manager for defining the subgraph content more elegantly within a with-block).

First usage option, with graph as the only argument:

>>> p = Graph(name='parent')
>>> p.edge('spam', 'eggs')

>>> c = Graph(name='child', node_attr={'shape': 'box'})
>>> c.edge('foo', 'bar')

>>> p.subgraph(c)

Second usage, with a with-block (omitting the graph argument):

>>> p = Graph(name='parent')
>>> p.edge('spam', 'eggs')

>>> with p.subgraph(name='child', node_attr={'shape': 'box'}) as c:
...    c.edge('foo', 'bar')

Both produce the same result:

>>> print(p.source)  
graph parent {
        spam -- eggs
    subgraph child {
        node [shape=box]
            foo -- bar
    }
}

Note

If the name of a subgraph begins with ‘cluster’ (all lowercase) the layout engine will treat it as a special cluster subgraph (example). Also see the Subgraphs and Clusters section of the DOT language documentaion.

Engines

To use a different layout command than the default dot when rendering your graph, use the engine argument when creating your graph.

>>> g = Graph(engine='neato')

You can also change the engine attribute of an existing instance:

>>> dot.engine = 'circo'

Custom DOT statements

To add arbitrary statements to the created DOT source, use the body attribute of the Graph or Digraph object. It holds the verbatim list of lines to be written to the source file. Use its append() or extend() method:

>>> rt = Digraph(comment='The Round Table')

>>> rt.body.append('\t\t"King Arthur" -> {\n\t\t\t"Sir Bedevere", "Sir Lancelot"\n\t\t}')
>>> rt.edge('Sir Bedevere', 'Sir Lancelot', constraint='false')

>>> print(rt.source)  
// The Round Table
digraph {
        "King Arthur" -> {
            "Sir Bedevere", "Sir Lancelot"
        }
        "Sir Bedevere" -> "Sir Lancelot" [constraint=false]
}

Note that you might need to correctly quote/escape identifiers and strings containing whitespace or other special characters when using this method.

Using raw DOT

To render a ready-made DOT source code string (instead of assembling one with the higher-level interface of Graph or Digraph), create a Source object holding your DOT string:

>>> from graphviz import Source

>>> src = Source('digraph "the holy hand grenade" { rankdir=LR; 1 -> 2 -> 3 -> lob }')

>>> src  
<graphviz.files.Source object at 0x...>

Use the render()-method to save and render it:

>>> src.render('test-output/holy-grenade.gv', view=True)  
'test-output/holy-grenade.gv.pdf'
_images/holy-grenade.svg

Apart from the missing editing methods, Source objects are the same as the higher-level graph objects (pipe()-method, format, engine, Jupyter notebook repr, etc.), see above.

Examples

Examples

See the examples directory in the source repository/distribution.

hello.py

# hello.py - http://www.graphviz.org/content/hello

from graphviz import Digraph

g = Digraph('G', filename='hello.gv')

g.edge('Hello', 'World')

g.view()
_images/hello.svg

process.py

# process.py - http://www.graphviz.org/content/process

from graphviz import Graph

g = Graph('G', filename='process.gv', engine='sfdp')

g.edge('run', 'intr')
g.edge('intr', 'runbl')
g.edge('runbl', 'run')
g.edge('run', 'kernel')
g.edge('kernel', 'zombie')
g.edge('kernel', 'sleep')
g.edge('kernel', 'runmem')
g.edge('sleep', 'swap')
g.edge('swap', 'runswap')
g.edge('runswap', 'new')
g.edge('runswap', 'runmem')
g.edge('new', 'runmem')
g.edge('sleep', 'runmem')

g.view()
_images/process.svg

fsm.py

# fsm.py - http://www.graphviz.org/content/fsm

from graphviz import Digraph

f = Digraph('finite_state_machine', filename='fsm.gv')
f.attr(rankdir='LR', size='8,5')

f.attr('node', shape='doublecircle')
f.node('LR_0')
f.node('LR_3')
f.node('LR_4')
f.node('LR_8')

f.attr('node', shape='circle')
f.edge('LR_0', 'LR_2', label='SS(B)')
f.edge('LR_0', 'LR_1', label='SS(S)')
f.edge('LR_1', 'LR_3', label='S($end)')
f.edge('LR_2', 'LR_6', label='SS(b)')
f.edge('LR_2', 'LR_5', label='SS(a)')
f.edge('LR_2', 'LR_4', label='S(A)')
f.edge('LR_5', 'LR_7', label='S(b)')
f.edge('LR_5', 'LR_5', label='S(a)')
f.edge('LR_6', 'LR_6', label='S(b)')
f.edge('LR_6', 'LR_5', label='S(a)')
f.edge('LR_7', 'LR_8', label='S(b)')
f.edge('LR_7', 'LR_5', label='S(a)')
f.edge('LR_8', 'LR_6', label='S(b)')
f.edge('LR_8', 'LR_5', label='S(a)')

f.view()
_images/fsm.svg

cluster.py

# cluster.py - http://www.graphviz.org/content/cluster

from graphviz import Digraph

g = Digraph('G', filename='cluster.gv')

# NOTE: the subgraph name needs to begin with 'cluster' (all lowercase)
#       so that Graphviz recognizes it as a special cluster subgraph

with g.subgraph(name='cluster_0') as c:
    c.attr(style='filled')
    c.attr(color='lightgrey')
    c.node_attr.update(style='filled', color='white')
    c.edges([('a0', 'a1'), ('a1', 'a2'), ('a2', 'a3')])
    c.attr(label='process #1')

with g.subgraph(name='cluster_1') as c:
    c.node_attr.update(style='filled')
    c.edges([('b0', 'b1'), ('b1', 'b2'), ('b2', 'b3')])
    c.attr(label='process #2')
    c.attr(color='blue')

g.edge('start', 'a0')
g.edge('start', 'b0')
g.edge('a1', 'b3')
g.edge('b2', 'a3')
g.edge('a3', 'a0')
g.edge('a3', 'end')
g.edge('b3', 'end')

g.node('start', shape='Mdiamond')
g.node('end', shape='Msquare')

g.view()
_images/cluster.svg

er.py

# er.py - http://www.graphviz.org/content/ER

from graphviz import Graph

e = Graph('ER', filename='er.gv', engine='neato')

e.attr('node', shape='box')
e.node('course')
e.node('institute')
e.node('student')

e.attr('node', shape='ellipse')
e.node('name0', label='name')
e.node('name1', label='name')
e.node('name2', label='name')
e.node('code')
e.node('grade')
e.node('number')

e.attr('node', shape='diamond', style='filled', color='lightgrey')
e.node('C-I')
e.node('S-C')
e.node('S-I')

e.edge('name0', 'course')
e.edge('code', 'course')
e.edge('course', 'C-I', label='n', len='1.00')
e.edge('C-I', 'institute', label='1', len='1.00')
e.edge('institute', 'name1')
e.edge('institute', 'S-I', label='1', len='1.00')
e.edge('S-I', 'student', label='n', len='1.00')
e.edge('student', 'grade')
e.edge('student', 'name2')
e.edge('student', 'number')
e.edge('student', 'S-C', label='m', len='1.00')
e.edge('S-C', 'course', label='n', len='1.00')

e.attr(label=r'\n\nEntity Relation Diagram\ndrawn by NEATO')
e.attr(fontsize='20')

e.view()
_images/er.svg

unix.py

# unix.py - http://www.graphviz.org/content/unix

from graphviz import Digraph

u = Digraph('unix', filename='unix.gv')
u.attr(size='6,6')
u.node_attr.update(color='lightblue2', style='filled')

u.edge('5th Edition', '6th Edition')
u.edge('5th Edition', 'PWB 1.0')
u.edge('6th Edition', 'LSX')
u.edge('6th Edition', '1 BSD')
u.edge('6th Edition', 'Mini Unix')
u.edge('6th Edition', 'Wollongong')
u.edge('6th Edition', 'Interdata')
u.edge('Interdata', 'Unix/TS 3.0')
u.edge('Interdata', 'PWB 2.0')
u.edge('Interdata', '7th Edition')
u.edge('7th Edition', '8th Edition')
u.edge('7th Edition', '32V')
u.edge('7th Edition', 'V7M')
u.edge('7th Edition', 'Ultrix-11')
u.edge('7th Edition', 'Xenix')
u.edge('7th Edition', 'UniPlus+')
u.edge('V7M', 'Ultrix-11')
u.edge('8th Edition', '9th Edition')
u.edge('1 BSD', '2 BSD')
u.edge('2 BSD', '2.8 BSD')
u.edge('2.8 BSD', 'Ultrix-11')
u.edge('2.8 BSD', '2.9 BSD')
u.edge('32V', '3 BSD')
u.edge('3 BSD', '4 BSD')
u.edge('4 BSD', '4.1 BSD')
u.edge('4.1 BSD', '4.2 BSD')
u.edge('4.1 BSD', '2.8 BSD')
u.edge('4.1 BSD', '8th Edition')
u.edge('4.2 BSD', '4.3 BSD')
u.edge('4.2 BSD', 'Ultrix-32')
u.edge('PWB 1.0', 'PWB 1.2')
u.edge('PWB 1.0', 'USG 1.0')
u.edge('PWB 1.2', 'PWB 2.0')
u.edge('USG 1.0', 'CB Unix 1')
u.edge('USG 1.0', 'USG 2.0')
u.edge('CB Unix 1', 'CB Unix 2')
u.edge('CB Unix 2', 'CB Unix 3')
u.edge('CB Unix 3', 'Unix/TS++')
u.edge('CB Unix 3', 'PDP-11 Sys V')
u.edge('USG 2.0', 'USG 3.0')
u.edge('USG 3.0', 'Unix/TS 3.0')
u.edge('PWB 2.0', 'Unix/TS 3.0')
u.edge('Unix/TS 1.0', 'Unix/TS 3.0')
u.edge('Unix/TS 3.0', 'TS 4.0')
u.edge('Unix/TS++', 'TS 4.0')
u.edge('CB Unix 3', 'TS 4.0')
u.edge('TS 4.0', 'System V.0')
u.edge('System V.0', 'System V.2')
u.edge('System V.2', 'System V.3')

u.view()
_images/unix.svg

structs.py

# structs.py - http://www.graphviz.org/doc/info/shapes.html#html

from graphviz import Digraph

s = Digraph('structs', node_attr={'shape': 'plaintext'})

s.node('struct1', '''<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
  <TR>
    <TD>left</TD>
    <TD PORT="f1">middle</TD>
    <TD PORT="f2">right</TD>
  </TR>
</TABLE>>''')
s.node('struct2', '''<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
  <TR>
    <TD PORT="f0">one</TD>
    <TD>two</TD>
  </TR>
</TABLE>>''')
s.node('struct3', '''<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
  <TR>
    <TD ROWSPAN="3">hello<BR/>world</TD>
    <TD COLSPAN="3">b</TD>
    <TD ROWSPAN="3">g</TD>
    <TD ROWSPAN="3">h</TD>
  </TR>
  <TR>
    <TD>c</TD>
    <TD PORT="here">d</TD>
    <TD>e</TD>
  </TR>
  <TR>
    <TD COLSPAN="3">f</TD>
  </TR>
</TABLE>>''')

s.edges([('struct1:f1', 'struct2:f0'), ('struct1:f2', 'struct3:here')])

s.view()
_images/structs.svg

structs_revisited.py

# structs_revisited.py - http://www.graphviz.org/pdf/dotguide.pdf Figure 12

from graphviz import Digraph

s = Digraph('structs', filename='structs_revisited.gv', node_attr={'shape': 'record'})

s.node('struct1', '<f0> left|<f1> middle|<f2> right')
s.node('struct2', '<f0> one|<f1> two')
s.node('struct3', r'hello\nworld |{ b |{c|<here> d|e}| f}| g | h')

s.edges([('struct1:f1', 'struct2:f0'), ('struct1:f2', 'struct3:here')])

s.view()
_images/structs_revisited.svg

btree.py

# btree.py - http://www.graphviz.org/pdf/dotguide.pdf Figure 13

from graphviz import Digraph

g = Digraph('g', filename='btree.gv', node_attr={'shape': 'record', 'height': '.1'})

g.node('node0', '<f0> |<f1> G|<f2> ')
g.node('node1', '<f0> |<f1> E|<f2> ')
g.node('node2', '<f0> |<f1> B|<f2> ')
g.node('node3', '<f0> |<f1> F|<f2> ')
g.node('node4', '<f0> |<f1> R|<f2> ')
g.node('node5', '<f0> |<f1> H|<f2> ')
g.node('node6', '<f0> |<f1> Y|<f2> ')
g.node('node7', '<f0> |<f1> A|<f2> ')
g.node('node8', '<f0> |<f1> C|<f2> ')

g.edge('node0:f2', 'node4:f1')
g.edge('node0:f0', 'node1:f1')
g.edge('node1:f0', 'node2:f1')
g.edge('node1:f2', 'node3:f1')
g.edge('node2:f2', 'node8:f1')
g.edge('node2:f0', 'node7:f1')
g.edge('node4:f2', 'node6:f1')
g.edge('node4:f0', 'node5:f1')

g.view()
_images/btree.svg

traffic_lights.py

# traffic_lights.py - http://www.graphviz.org/content/traffic_lights

from graphviz import Digraph

t = Digraph('TrafficLights', filename='traffic_lights.gv', engine='neato')

t.attr('node', shape='box')
for i in (2, 1):
    t.node('gy%d' % i)
    t.node('yr%d' % i)
    t.node('rg%d' % i)

t.attr('node', shape='circle', fixedsize='true', width='0.9')
for i in (2, 1):
    t.node('green%d' % i)
    t.node('yellow%d' % i)
    t.node('red%d' % i)
    t.node('safe%d' % i)

for i, j in [(2, 1), (1, 2)]:
    t.edge('gy%d' % i, 'yellow%d' % i)
    t.edge('rg%d' % i, 'green%d' % i)
    t.edge('yr%d' % i, 'safe%d' % j)
    t.edge('yr%d' % i, 'red%d' % i)
    t.edge('safe%d' % i, 'rg%d' % i)
    t.edge('green%d' % i, 'gy%d' % i)
    t.edge('yellow%d' % i, 'yr%d' % i)
    t.edge('red%d' % i, 'rg%d' % i)

t.attr(overlap='false')
t.attr(label=r'PetriNet Model TrafficLights\n'
             r'Extracted from ConceptBase and layed out by Graphviz')
t.attr(fontsize='12')

t.view()
_images/traffic_lights.svg

fdpclust.py

# fdpclust.py - http://www.graphviz.org/content/fdpclust

from graphviz import Graph

g = Graph('G', filename='fdpclust.gv', engine='fdp')

g.node('e')

with g.subgraph(name='clusterA') as a:
    a.edge('a', 'b')
    with a.subgraph(name='clusterC') as c:
        c.edge('C', 'D')

with g.subgraph(name='clusterB') as b:
    b.edge('d', 'f')

g.edge('d', 'D')
g.edge('e', 'clusterB')
g.edge('clusterC', 'clusterB')

g.view()
_images/fdpclust.svg

cluster_edge.py

# cluster_edge.py - http://www.graphviz.org/pdf/dotguide.pdf Figure 20

from graphviz import Digraph

g = Digraph('G', filename='cluster_edge.gv')
g.attr(compound='true')

with g.subgraph(name='cluster0') as c:
    c.edges(['ab', 'ac', 'bd', 'cd'])

with g.subgraph(name='cluster1') as c:
    c.edges(['eg', 'ef'])

g.edge('b', 'f', lhead='cluster1')
g.edge('d', 'e')
g.edge('c', 'g', ltail='cluster0', lhead='cluster1')
g.edge('c', 'e', ltail='cluster0')
g.edge('d', 'h')

g.view()
_images/cluster_edge.svg

g_c_n.py

# http://www.graphviz.org/Gallery/gradient/g_c_n.html

from graphviz import Graph

g = Graph('G', filename='g_c_n.gv')
g.attr(bgcolor='purple:pink', label='agraph', fontcolor='white')

with g.subgraph(name='cluster1') as c:
    c.attr(fillcolor='blue:cyan', label='acluster', fontcolor='white',
           style='filled', gradientangle='270')
    c.attr('node', shape='box', fillcolor='red:yellow',
           style='filled', gradientangle='90')
    c.node('anode')

g.view()
_images/g_c_n.svg

angles.py

# angles.py - http://www.graphviz.org/Gallery/gradient/angles.html

from graphviz import Digraph

g = Digraph('G', filename='angles.gv')
g.attr(bgcolor='blue')

with g.subgraph(name='cluster_1') as c:
    c.attr(fontcolor='white')
    c.attr('node', shape='circle', style='filled', fillcolor='white:black',
           gradientangle='360', label='n9:360', fontcolor='black')
    c.node('n9')
    for i, a in zip(range(8, 0, -1), range(360 - 45, -1, -45)):
        c.attr('node', gradientangle='%d' % a, label='n%d:%d' % (i, a))
        c.node('n%d' % i)
    c.attr(label='Linear Angle Variations (white to black gradient)')

with g.subgraph(name='cluster_2') as c:
    c.attr(fontcolor='white')
    c.attr('node', shape='circle', style='radial', fillcolor='white:black',
           gradientangle='360', label='n18:360', fontcolor='black')
    c.node('n18')
    for i, a in zip(range(17, 9, -1), range(360 - 45, -1, -45)):
        c.attr('node', gradientangle='%d' % a, label='n%d:%d' % (i, a))
        c.node('n%d' % i)
    c.attr(label='Radial Angle Variations (white to black gradient)')

g.edge('n5', 'n14')

g.view()
_images/angles.svg

API Reference

API Reference

Note

The two main classes Graph and Digraph (for creating undirected vs. directed graphs) have exactly the same API. Their division reflects the fact that both graph types cannot be mixed.

Graph

class graphviz.Graph(name=None, comment=None, filename=None, directory=None, format=None, engine=None, encoding=None, graph_attr=None, node_attr=None, edge_attr=None, body=None, strict=False)

Graph source code in the DOT language.

Parameters:
  • name – Graph name used in the source code.
  • comment – Comment added to the first line of the source.
  • filename – Filename for saving the source (defaults to name + ‘.gv’).
  • directory – (Sub)directory for source saving and rendering.
  • format – Rendering output format (‘pdf’, ‘png’, ...).
  • engine – Layout command used (‘dot’, ‘neato’, ...).
  • encoding – Encoding for saving the source.
  • graph_attr – Mapping of (attribute, value) pairs for the graph.
  • node_attr – Mapping of (attribute, value) pairs set for all nodes.
  • edge_attr – Mapping of (attribute, value) pairs set for all edges.
  • body – Iterable of verbatim lines to add to the graph body.
  • strict (bool) – Rendering should merge multi-edges.

Note

All parameters are optional and can be changed under their corresponding attribute name after instance creation.

attr(kw=None, _attributes=None, **attrs)

Add a general or graph/node/edge attribute statement.

Parameters:
  • kw – Attributes target (None or ‘graph’, ‘node’, ‘edge’).
  • attrs – Attributes to be set (must be strings, may be empty).

See the usage examples in the User Guide.

copy()

Return a copied instance of the object.

edge(tail_name, head_name, label=None, _attributes=None, **attrs)

Create an edge between two nodes.

Parameters:
  • tail_name – Start node identifier.
  • head_name – End node identifier.
  • label – Caption to be displayed near the edge.
  • attrs – Any additional edge attributes (must be strings).
edges(tail_head_iter)

Create a bunch of edges.

Parameters:tail_head_iter – Iterable of (tail_name, head_name) pairs.
encoding

The encoding for the saved source file.

engine

The layout commmand used for rendering (‘dot’, ‘neato’, ...).

format

The output format used for rendering (‘pdf’, ‘png’, ...).

node(name, label=None, _attributes=None, **attrs)

Create a node.

Parameters:
  • name – Unique identifier for the node inside the source.
  • label – Caption to be displayed (defaults to the node name).
  • attrs – Any additional node attributes (must be strings).
pipe(format=None)

Return the source piped through the Graphviz layout command.

Parameters:

format – The output format used for rendering (‘pdf’, ‘png’, etc.).

Returns:

Binary (encoded) stdout of the layout command.

Raises:
render(filename=None, directory=None, view=False, cleanup=False)

Save the source to file and render with the Graphviz engine.

Parameters:
  • filename – Filename for saving the source (defaults to name + ‘.gv’)
  • directory – (Sub)directory for source saving and rendering.
  • view (bool) – Open the rendered result with the default application.
  • cleanup (bool) – Delete the source file after rendering.
Returns:

The (possibly relative) path of the rendered file.

Raises:
save(filename=None, directory=None)

Save the DOT source to file. Ensure the file ends with a newline.

Parameters:
  • filename – Filename for saving the source (defaults to name + ‘.gv’)
  • directory – (Sub)directory for source saving and rendering.
Returns:

The (possibly relative) path of the saved source file.

source

The DOT source code as string.

subgraph(graph=None, name=None, comment=None, graph_attr=None, node_attr=None, edge_attr=None, body=None)

Add the current content of the given sole graph argument as subgraph or return a context manager returning a new graph instance created with the given (name, comment, etc.) arguments whose content is added as subgraph when leaving the context manager’s with-block.

Parameters:
  • graph – An instance of the same kind (Graph, Digraph) as the current graph (sole argument in non-with-block use).
  • name – Subgraph name (with-block use).
  • comment – Subgraph comment (with-block use).
  • graph_attr – Subgraph-level attribute-value mapping (with-block use).
  • node_attr – Node-level attribute-value mapping (with-block use).
  • edge_attr – Edge-level attribute-value mapping (with-block use).
  • body – Verbatim lines to add to the subgraph body (with-block use).

See the usage examples in the User Guide.

Note

If the name of the subgraph begins with ‘cluster’ (all lowercase) the layout engine will treat it as a special cluster subgraph.

view(filename=None, directory=None, cleanup=False)

Save the source to file, open the rendered result in a viewer.

Parameters:
  • filename – Filename for saving the source (defaults to name + ‘.gv’)
  • directory – (Sub)directory for source saving and rendering.
  • cleanup (bool) – Delete the source file after rendering.
Returns:

The (possibly relative) path of the rendered file.

Raises:

Short-cut method for calling render() with view=True.

Digraph

class graphviz.Digraph(name=None, comment=None, filename=None, directory=None, format=None, engine=None, encoding=None, graph_attr=None, node_attr=None, edge_attr=None, body=None, strict=False)

Directed graph source code in the DOT language.

Parameters:
  • name – Graph name used in the source code.
  • comment – Comment added to the first line of the source.
  • filename – Filename for saving the source (defaults to name + ‘.gv’).
  • directory – (Sub)directory for source saving and rendering.
  • format – Rendering output format (‘pdf’, ‘png’, ...).
  • engine – Layout command used (‘dot’, ‘neato’, ...).
  • encoding – Encoding for saving the source.
  • graph_attr – Mapping of (attribute, value) pairs for the graph.
  • node_attr – Mapping of (attribute, value) pairs set for all nodes.
  • edge_attr – Mapping of (attribute, value) pairs set for all edges.
  • body – Iterable of verbatim lines to add to the graph body.
  • strict (bool) – Rendering should merge multi-edges.

Note

All parameters are optional and can be changed under their corresponding attribute name after instance creation.

attr(kw=None, _attributes=None, **attrs)

Add a general or graph/node/edge attribute statement.

Parameters:
  • kw – Attributes target (None or ‘graph’, ‘node’, ‘edge’).
  • attrs – Attributes to be set (must be strings, may be empty).

See the usage examples in the User Guide.

copy()

Return a copied instance of the object.

edge(tail_name, head_name, label=None, _attributes=None, **attrs)

Create an edge between two nodes.

Parameters:
  • tail_name – Start node identifier.
  • head_name – End node identifier.
  • label – Caption to be displayed near the edge.
  • attrs – Any additional edge attributes (must be strings).
edges(tail_head_iter)

Create a bunch of edges.

Parameters:tail_head_iter – Iterable of (tail_name, head_name) pairs.
encoding

The encoding for the saved source file.

engine

The layout commmand used for rendering (‘dot’, ‘neato’, ...).

format

The output format used for rendering (‘pdf’, ‘png’, ...).

node(name, label=None, _attributes=None, **attrs)

Create a node.

Parameters:
  • name – Unique identifier for the node inside the source.
  • label – Caption to be displayed (defaults to the node name).
  • attrs – Any additional node attributes (must be strings).
pipe(format=None)

Return the source piped through the Graphviz layout command.

Parameters:

format – The output format used for rendering (‘pdf’, ‘png’, etc.).

Returns:

Binary (encoded) stdout of the layout command.

Raises:
render(filename=None, directory=None, view=False, cleanup=False)

Save the source to file and render with the Graphviz engine.

Parameters:
  • filename – Filename for saving the source (defaults to name + ‘.gv’)
  • directory – (Sub)directory for source saving and rendering.
  • view (bool) – Open the rendered result with the default application.
  • cleanup (bool) – Delete the source file after rendering.
Returns:

The (possibly relative) path of the rendered file.

Raises:
save(filename=None, directory=None)

Save the DOT source to file. Ensure the file ends with a newline.

Parameters:
  • filename – Filename for saving the source (defaults to name + ‘.gv’)
  • directory – (Sub)directory for source saving and rendering.
Returns:

The (possibly relative) path of the saved source file.

source

The DOT source code as string.

subgraph(graph=None, name=None, comment=None, graph_attr=None, node_attr=None, edge_attr=None, body=None)

Add the current content of the given sole graph argument as subgraph or return a context manager returning a new graph instance created with the given (name, comment, etc.) arguments whose content is added as subgraph when leaving the context manager’s with-block.

Parameters:
  • graph – An instance of the same kind (Graph, Digraph) as the current graph (sole argument in non-with-block use).
  • name – Subgraph name (with-block use).
  • comment – Subgraph comment (with-block use).
  • graph_attr – Subgraph-level attribute-value mapping (with-block use).
  • node_attr – Node-level attribute-value mapping (with-block use).
  • edge_attr – Edge-level attribute-value mapping (with-block use).
  • body – Verbatim lines to add to the subgraph body (with-block use).

See the usage examples in the User Guide.

Note

If the name of the subgraph begins with ‘cluster’ (all lowercase) the layout engine will treat it as a special cluster subgraph.

view(filename=None, directory=None, cleanup=False)

Save the source to file, open the rendered result in a viewer.

Parameters:
  • filename – Filename for saving the source (defaults to name + ‘.gv’)
  • directory – (Sub)directory for source saving and rendering.
  • cleanup (bool) – Delete the source file after rendering.
Returns:

The (possibly relative) path of the rendered file.

Raises:

Short-cut method for calling render() with view=True.

Source

class graphviz.Source(source, filename=None, directory=None, format=None, engine=None, encoding=None)

Verbatim DOT source code string to be rendered by Graphviz.

Parameters:
  • source – The verbatim DOT source code string.
  • filename – Filename for saving the source (defaults to name + ‘.gv’).
  • directory – (Sub)directory for source saving and rendering.
  • format – Rendering output format (‘pdf’, ‘png’, ...).
  • engine – Layout command used (‘dot’, ‘neato’, ...).
  • encoding – Encoding for saving the source.

Note

All parameters except source are optional and can be changed under their corresponding attribute name after instance creation.

copy()

Return a copied instance of the object.

encoding

The encoding for the saved source file.

engine

The layout commmand used for rendering (‘dot’, ‘neato’, ...).

format

The output format used for rendering (‘pdf’, ‘png’, ...).

pipe(format=None)

Return the source piped through the Graphviz layout command.

Parameters:

format – The output format used for rendering (‘pdf’, ‘png’, etc.).

Returns:

Binary (encoded) stdout of the layout command.

Raises:
render(filename=None, directory=None, view=False, cleanup=False)

Save the source to file and render with the Graphviz engine.

Parameters:
  • filename – Filename for saving the source (defaults to name + ‘.gv’)
  • directory – (Sub)directory for source saving and rendering.
  • view (bool) – Open the rendered result with the default application.
  • cleanup (bool) – Delete the source file after rendering.
Returns:

The (possibly relative) path of the rendered file.

Raises:
save(filename=None, directory=None)

Save the DOT source to file. Ensure the file ends with a newline.

Parameters:
  • filename – Filename for saving the source (defaults to name + ‘.gv’)
  • directory – (Sub)directory for source saving and rendering.
Returns:

The (possibly relative) path of the saved source file.

view(filename=None, directory=None, cleanup=False)

Save the source to file, open the rendered result in a viewer.

Parameters:
  • filename – Filename for saving the source (defaults to name + ‘.gv’)
  • directory – (Sub)directory for source saving and rendering.
  • cleanup (bool) – Delete the source file after rendering.
Returns:

The (possibly relative) path of the rendered file.

Raises:

Short-cut method for calling render() with view=True.

Low-level functions

The functions in this section are provided to work directly with existing files and strings instead of using the object-oriented DOT creation methods documented above.

graphviz.render(engine, format, filepath, quiet=False)

Render file with Graphviz engine into format, return result filename.

Parameters:
  • engine – The layout commmand used for rendering (‘dot’, ‘neato’, ...).
  • format – The output format used for rendering (‘pdf’, ‘png’, ...).
  • filepath – Path to the DOT source file to render.
  • quiet (bool) – Suppress stderr output on non-zero exit status.
Returns:

The (possibly relative) path of the rendered file.

Raises:
graphviz.pipe(engine, format, data, quiet=False)

Return data piped through Graphviz engine into format.

Parameters:
  • engine – The layout commmand used for rendering (‘dot’, ‘neato’, ...).
  • format – The output format used for rendering (‘pdf’, ‘png’, ...).
  • data – The binary (encoded) DOT source string to render.
  • quiet (bool) – Suppress stderr output on non-zero exit status.
Returns:

Binary (encoded) stdout of the layout command.

Raises:
graphviz.view(filepath)

Open filepath with its default viewing application (platform-specific).

Raises:RuntimeError – If the current platform is not supported.

Other

graphviz.ENGINES

Set of known layout commands used for rendering (‘dot’, ‘neato’, ...)

graphviz.FORMATS

Set of known output formats for rendering (‘pdf’, ‘png’, ...)

graphviz.ExecutableNotFound

Exception raised if the Graphviz executable is not found.

Project Info

Changelog

Version 0.7.1

Fix TypeError in graphviz.pipe() with invalid dot code under Python 3.

Add copy()-method for Graph, Digraph, and Source.

Add graphviz.render(..., quiet=True).

Fix graphivz.view() exception on unsupported platform.

Raise a dedicated RuntimeError subclass graphviz.ExecutableNotFound when the Graphviz executables are not found.

Port tests from nose/unittest to pytest, extend, use mocks.

Version 0.7

Support setting top-level attrs with g.attr(key=value).

Add context manager usage of subgraph() for adding a subgraph in a with-block.

Add json-based output formats to known FORMATS (Graphviz 2.40+).

Drop extra indent level for DOT source with nonempty graph/node/edge_attr.

Add a final newline to a saved DOT source file if it does not end with one.

Raise subprocess.CalledProcessError on non-zero exit status from rendering.

Raise early when adding a subgraph() with strict=True (avoid DOT syntax error).

Make undocumented quote(), quote_edge(), and attributes() methods private.

Version 0.6

Drop Python 2.6 support (use graphviz<0.6 there).

Improve tests for mkdirs().

Better document adding custom DOT using the body attribute.

Add view()-support for FreeBSD (pull request Julien Gamba).

Version 0.5.2

Add ENGINES and FORMATS to the documented public API.

Version 0.5.1

Fixed PY3 compatibility.

Version 0.5

Add low-level functions render(), pipe(), and view() for directly working with existing files and strings.

Support all render()-arguments in the view()-short-cut-method.

Version 0.4.10

Added patchwork engine.

Version 0.4.9

Add support for ‘strict’ graphs and digraphs.

Hide render/pipe subrocess console window on Windows when invoked from non-console process (e.g. from IDLE).

Improve documentation markup/wording.

Make TestNoent more robust.

Version 0.4.8

Make _repr_svg_ available on Source (pull request RafalSkolasinski).

Version 0.4.7

Fixed view()-method on Linux under Python 3 (pull request Antony Lee).

Version 0.4.6

Fixed view()-method on Linux and Darwin (pull request Eric L. Frederich).

Version 0.4.5

Added example for HTML-like labels (structs.py).

Added Source class for rendering verbatim DOT source code.

Added Python 2.6 support (pull request Jim Crist).

Version 0.4.4

Added the pipe()-method directly returning the stdout of the rendering.

Added _repr_svg_ for inline rendering in IPython notebooks.

Version 0.4.3

Added examples generating some of the graphs from the Graphviz Gallery.

Added sphinx-based API documentation.

Version 0.4.2

Added support for HTML-like labels.

Version 0.4.1

Added support for less common output formats. Removed dropped formats (dia, pcl).

Added osage layout engine.

Documented format and engine options in the README.

The view() convenience method now returns the result file name (like render()).

Version 0.4

Added attr() method for inline switching of node/edge attributes.

Added subgraph() method (obsoletes separate Subgraph class).

Add cleanup option to render().

Replaced dry option on render() with separate save() method.

Removed undocumented append() and extend() methods (if needed, the body attribute can be edited directly).

Version 0.3.5

Skip empty comment when creating DOT source.

Document graph_attr, node_attr, and edge_attr in the README.

More informative exception when Graphviz excutables cannot be called.

Version 0.3.4

Fixed missing identifier quoting for DOT keywords (thanks to Paulo Urio).

Version 0.3.3

Made format and engine case-insensitive.

Version 0.3.2

Indent graph_attr, node_attr, and edge_attr lines, adapt nodes and edges.

Version 0.3.1

Fixed view() failing on paths with forward slashes on Windows.

Version 0.3

Added Python 3.3+ support.

Made attributes order stable (sorting plain dicts).

Fixed edgeop in undirected graphs.

Version 0.2.2

Support pdf opening on Linux.

Fixed rendering filenames w/spaces.

Version 0.2.1

Fixed rendering on Mac OS X.

Version 0.2

Added format selection, use PDF as default. Added engines selection, use dot as default. Added source encoding, use UTF-8 as default.

Changed constructor arguments order, removed compile and save method, reimplemented compilation in render method, make interface more similar to gv.3python (backwards incompatible change).

Double-quote-sign escaping, attribute list quoting.

mkdirs now correctly supports current directory filenames.

Version 0.1.1

Removed automatic ‘-‘ to ‘&minus;’ replacement from labels.

Fixed documentation typos.

Version 0.1

First public release.

License

The MIT License (MIT)

Copyright (c) 2013-2017 Sebastian Bank

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.