Code Monkey home page Code Monkey logo

graphviz's Introduction

Graphviz

Latest PyPI Version License Supported Python Versions Wheel format Monthly downloads

Build Codecov Readthedocs (stable) Readthedocs (latest)

Binder (stable)

This package facilitates the creation and rendering of graph descriptions in the DOT language of the Graphviz graph drawing software (upstream 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 (formerly known as IPython notebooks, example, nbviewer) as well as the Jupyter QtConsole.

Links

Installation

This package runs under Python 3.8+, use pip to install:

$ pip install graphviz

To render the generated DOT source code, you also need to install Graphviz (download page, archived versions, installation procedure for Windows).

Make sure that the directory containing the dot executable is on your systems' PATH (sometimes done by the installer; setting PATH on Linux, Mac, and Windows).

Anaconda: see the conda-forge package conda-forge/python-graphviz (feedstock), which should automatically conda install conda-forge/graphviz (feedstock) as dependency.

Quickstart

Create a graph object:

>>> import graphviz  # doctest: +NO_EXE
>>> dot = graphviz.Digraph(comment='The Round Table')
>>> dot  #doctest: +ELLIPSIS
<graphviz.graphs.Digraph object at 0x...>

Add nodes and edges:

>>> dot.node('A', 'King Arthur')  # doctest: +NO_EXE
>>> 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)  # doctest: +NORMALIZE_WHITESPACE +NO_EXE
// 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 (skip/ignore any doctest_mark_exe() lines):

>>> doctest_mark_exe()  # skip this line

>>> dot.render('doctest-output/round-table.gv').replace('\\', '/')
'doctest-output/round-table.gv.pdf'

Save and render and view the result:

>>> doctest_mark_exe()  # skip this line

>>> dot.render('doctest-output/round-table.gv', view=True)  # doctest: +SKIP
'doctest-output/round-table.gv.pdf'

round-table.svg

Caveat: Backslash-escapes and strings of the form <...> have a special meaning in the DOT language. If you need to render arbitrary strings (e.g. from user input), check the details in the user guide.

See also

License

This package is distributed under the MIT license.

graphviz's People

Contributors

anntzer avatar bastbnl avatar bmaxv avatar boeddeker avatar charlietle avatar dantownsend avatar davidalber avatar daviey avatar dngros avatar egberts avatar eli-schwartz avatar ericfrederich avatar eumiro avatar jcrist avatar kianmeng avatar lukhio avatar mathstuf avatar mgoral avatar paulourio avatar rafalskolasinski avatar xflr6 avatar yegle avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

graphviz's Issues

Tests failing

When I run nosetests, I am getting two failures. Here are the logs

..........spam:E: invalid option "T"
spam:I: usage is "spam [-vCeghlprx] [-b bctf] [-f error_file] [-c catalog_sysid] [-D dir] [-a link_type] [-A arch] [-E max_errors] [-i entity] [-w warning_type] [-m omittag|shortref|net|emptytag|unclosed|attname|attvalue|attspec|current|shorttag|rank|reserved] [-o entity_name] sysid..."
Fspam:E: invalid option "T"
spam:I: usage is "spam [-vCeghlprx] [-b bctf] [-f error_file] [-c catalog_sysid] [-D dir] [-a link_type] [-A arch] [-E max_errors] [-i entity] [-w warning_type] [-m omittag|shortref|net|emptytag|unclosed|attname|attvalue|attspec|current|shorttag|rank|reserved] [-o entity_name] sysid..."
F................
======================================================================
FAIL: test_pipe (test_files.TestNoent)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/balasankarc/git/graphviz/tests/test_files.py", line 50, in test_pipe
    self.file.pipe()
AssertionError: RuntimeError not raised

======================================================================
FAIL: test_render (test_files.TestNoent)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/balasankarc/git/graphviz/tests/test_files.py", line 54, in test_render
    self.file.render()
AssertionError: RuntimeError not raised

Name                  Stmts   Miss  Cover   Missing
---------------------------------------------------
graphviz.py               9      0   100%   
graphviz/_compat.py       2      0   100%   
graphviz/dot.py          71      0   100%   
graphviz/files.py       124     14    89%   163-165, 191, 220-222, 231, 246-248, 262, 273, 278
graphviz/lang.py         40      0   100%   
graphviz/tools.py        18      1    94%   38
---------------------------------------------------
TOTAL                   264     15    94%   
----------------------------------------------------------------------
Ran 28 tests in 0.433s

FAILED (failures=2)

How to save result with Source object

Using the Source object like in

from graphviz import Source

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

how can I save a the result in a file (result.png)?

Bye Gerhard

How do you add dot executables to system PATH in mac?

When I run graphviz I get the following error

graphviz.backend.ExecutableNotFound: failed to execute ['dot', '-Tpdf', '-O', 'test-output/aoc.gv.pdf'], make sure the Graphviz executables are on your systems' PATH

I don't know what the graphviz executables are. In any case, my best guess is that I have to add the path of the module that uses graphviz or I have to add the graphviz module to my .bash_profile. Currently, my bash_profile has this line:

PATH="/Library/Frameworks/Python.framework/Versions/3.6/bin:${PATH}

So I tried adding the path of where the module that uses Graphviz is located which is

/Users/kylefoley/PycharmProjects/inference_engine2/inference2/proofs/other/use_graphviz.py

Plus the graphviz module itself which is:

/library/frameworks/python.framework/versions/3.6/lib/python3.6/site-packages/graphviz/

Making the final product to be:

PATH="/Library/Frameworks/Python.framework/Versions/3.6/bin:${PATH}:/Users/kylefoley/PycharmProjects/inference_engine2/inference2/proofs/other/use_graphviz.py:/library/frameworks/python.framework/versions/3.6/lib/python3.6/site-packages/graphviz/"

But that did not work. I need to know what string I have to add to the PATH.

Is it possible to indicate node rank?

I can't figure out to solve the problems posed by this and this stackoverflow's questions. Actually, I'm trying to reproduce this graph and can't figure out how to input the rank information on the python side.

Any directions?

By the way, thanks for such a nice library!

Bug with nosetests and --with-xunit

Install nosetests and the with-xunit support

then run the following test with nosetests --with-xunit

from graphviz import Digraph, Graph

def test_broken():
    dot = Digraph(name='name', format='plain', graph_attr={'rankdir':'LR'})
    dot.attr(style='filled')
    dot.node_attr.update(style='filled', color='white')

    dot.node('1','1', {'color': 'not-a-colour'})
    dot.node('2','2', {'color': 'not-a-colour'})
    dot.edge('1','2', None, {'color': 'not-a-colour'})

    dot.render('test', view=False)

and it fails with

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/nose/case.py", line 198, in runTest
    self.test(*self.arg)
  File "/Users/marsje/src/github/graphviz-error/test_gv.py", line 12, in test_broken
    dot.render('test', view=False)
  File "/usr/local/lib/python3.7/site-packages/graphviz/files.py", line 176, in render
    rendered = backend.render(self._engine, self._format, filepath)
  File "/usr/local/lib/python3.7/site-packages/graphviz/backend.py", line 142, in render
    run(cmd, capture_output=True, check=True, quiet=quiet)
  File "/usr/local/lib/python3.7/site-packages/graphviz/backend.py", line 120, in run
    stderr_write_bytes(err, flush=True)
  File "/usr/local/lib/python3.7/site-packages/graphviz/_compat.py", line 41, in stderr_write_bytes
    encoding = sys.stderr.encoding or sys.getdefaultencoding()
AttributeError: 'Tee' object has no attribute 'encoding'

Seems like its trying to do something with stderr (as it is complaining about a colour not being a colour) but then failing.

I came across this using mock to mock out my colour selection and got round it by mocking a real colour, but then other stderr messages can break it to, I would think

Python 3.x on mac

error encoding

only on windows i have this error:
'NoneType ' has not objects encoding line 43 in _compact.py

I fixed it commenting the lines 156 to 159 in backend.py

Iterate through nodes and edges?

I've looked through the documentation, and I've also glanced at the source code, so my apologies if I've missed this feature, but could we get methods that allow us to iterate through the nodes and/or edges that have been added to an existing Dot object?

Off the top of my head, one way to implement this would to have attributes of _node_list and _edge_list that are initialized at []. They're then updated when adding nodes and edges, and we can tack on a nodes method to return _node_list and allow calling the edges method with no (user-supplied) arguments to get a simple iterator of edge data, eg:

def node(self, name, label=None, _attributes=None, **attrs):
        """Create a node.
        Args:
            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).
        """
        name = self.quote(name)
        attributes = self.attributes(label, attrs, _attributes)
        self.body.append(self._node % (name, attributes))
        node_dict = {"name": name, "label": label}
        self._nodes.append({"name": name, "label": label, "attributes": attrs})

def nodes(self):
    """Provides a list of node data (in the form of dicts) for nodes that have been added."""
    return self._nodes

def edge(self, tail_name, head_name, label=None, _attributes=None, **attrs):
        """Create an edge between two nodes.
        Args:
            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).
        """
        tail_name = self.quote_edge(tail_name)
        head_name = self.quote_edge(head_name)
        attributes = self.attributes(label, attrs, _attributes)
        edge = self._edge % (tail_name, head_name, attributes)
        self.body.append(edge)
        self._edges.append({"tail": tail_name, "head": head_name, "attributes": attrs})

def edges(self, tail_head_iter=None):
        """Create a bunch of edges or iterate through existing edges.
        Args:
            tail_head_iter: Iterable of (tail_name, head_name) pairs or None.
                If not provided, then a list of edge data is returned.
        """
        if tail_head_iter is not None:
            edge = self._edge_plain
            quote = self.quote_edge
            tail_head_iter = [(quote(t), quote(h)) for t, h in tail_head_iter]
            self.body.extend(edge % (t, h)
                for t, h in tail_head_iter)
            self._edges.extend([{"tail": t, "head": h} for t, h in tail_head_iter])
        else:
            return self._edges

This is probably a bit incorrect, as _attributes and attrs probably need to be merged. Now that I think about it, I'm not sure why there are two arguments that seem to provide the same thing (_attributes is supposed to be an object, right?). Also, we could be fancier and have separate Node and Edge objects to hold this data instead of dicts, but I'm not sure that's terribly necessary.

I'd be willing to make a pull request if this feature would be welcome.

report/resolve broken exit status on trusty

$ echo 'nongraph' | dot -Tsvg && echo $?
Warning: <stdin>: syntax error in line 1 near 'nongraph'
0

$ dot -V
dot - graphviz version 2.36.0 (20140111.2315)

$ apt-cache policy graphviz
graphviz:
  Installed: 2.36.0-0ubuntu3.2

$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.5 LTS"

Notify of non-existent dot in a more obvious manner.

Minor usability tweak; wrapping the dot call line (this one) in a try/except OSError block that raises a more appropriate exception would be nice. I hopped on a new machine that I thought had graphviz installed and was getting the inexplicable:

 OSError: [Errno 2] No such file or directory

which I thought might have been because I wasn't specifying the name of the dotfile, it was locked, unreadable, or something else (obviously not that in retrospect, that wouldn't be a Python error).

Support for HTML labels?

How do I create the following graph using your library (this is from the official website of GraphViz):

digraph structs {
    node [shape=plaintext];

    struct1 [label=<<TABLE>
    <TR>
        <TD>line 1</TD>
        <TD BGCOLOR="blue"><FONT COLOR="white">line2</FONT></TD>
        <TD BGCOLOR="gray"><FONT POINT-SIZE="24.0">line3</FONT></TD>
        <TD BGCOLOR="yellow"><FONT POINT-SIZE="24.0" FACE="ambrosia">line4</FONT></TD>
        <TD>
          <TABLE CELLPADDING="0" BORDER="0" CELLSPACING="0">
          <TR>
            <TD><FONT COLOR="green">Mixed</FONT></TD>
            <TD><FONT COLOR="red">fonts</FONT></TD>
          </TR>
          </TABLE>
        </TD>
    </TR>
    </TABLE>>];
}

Add support for literal colons in node name (WAS: escaping of `::`)

from graphviz import Digraph

print("Bug 1: strange generated DOT source")
dot = Digraph(filename='bug-escaping-1.dot', format='png')

n1 = "A"
n2 = "::"
dot.node(n1)
dot.node(n2)
dot.edge(n1, n2)

print(dot.source)
dot.render()


print("Bug 2: crash")
dot = Digraph(filename='bug-escaping-2.dot', format='png')

n1 = "A"
n2 = "'B::C'"
dot.node(n1)
dot.node(n2)
dot.edge(n1, n2)

print(dot.source)
dot.render()

Result:

$ python3 bug-escaping.py 
Bug 1: strange generated DOT source
digraph {
        A
        "::"
        A -> "":""
}
Bug 2: crash
digraph {
        A
        "'B::C'"
        A -> "'B":"":C'
}
Error: bug-escaping-2.dot: syntax error in line 4 near '''
Traceback (most recent call last):
  File "bug-escaping.py", line 26, in <module>
    dot.render()
  File "/home/thomas/.local/lib/python3.5/site-packages/graphviz/files.py", line 176, in render
    rendered = backend.render(self._engine, self._format, filepath)
  File "/home/thomas/.local/lib/python3.5/site-packages/graphviz/backend.py", line 124, in render
    subprocess.check_call(args, startupinfo=STARTUPINFO, stderr=stderr)
  File "/usr/lib/python3.5/subprocess.py", line 581, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['dot', '-Tpng', '-O', 'bug-escaping-2.dot']' returned non-zero exit status 1

Info:

  • graphviz 0.8.3
  • Python 3.5.2

maybe change the linked readthedocs version to 'stable' instead of 'latest'

hey,
I installed the package via pip install and then wanted to try out the examples in your documentation. The fsm.py example gave an error and this is when I noticed that I was at the 'latest' branch where the parameter "kw" of the method attr() has now a default value.
So I think it would make sense to link to the 'stable' branch instead so that people don't get confused or notify somehow that if you installed via pip then you should go to 'stable'.
Best,
Andrej

python3.7 test failure on UTF-8 encoding

When building graphviz-0.9 with python37, two tests fail like this:

PYTHONPATH=/sw/build.build/graphviz-py37-0.9-1/graphviz-0.9/build/lib:$PYTHONPATH /sw/bin/python3.7 run-tests.py || exit 2
==================================================================================== test session starts ====================================================================================
platform darwin -- Python 3.7.0, pytest-3.6.4, py-1.5.4, pluggy-0.7.1
rootdir: /sw/build.build/graphviz-py37-0.9-1/graphviz-0.9, inifile: setup.cfg
plugins: mock-1.10.0, cov-2.6.0, hypothesis-3.69.2
collected 86 items                                                                                                                                                                          

README.rst .                                                                                                                                                                          [  1%]
docs/manual.rst Fontconfig warning: ignoring UTF-8: not a valid region tag
Fontconfig warning: ignoring UTF-8: not a valid region tag
.                                                                                                                                                                     [  2%]
graphviz/__init__.py .                                                                                                                                                                [  3%]
graphviz/dot.py .                                                                                                                                                                     [  4%]
graphviz/lang.py .....                                                                                                                                                                [ 10%]
graphviz/tools.py ..                                                                                                                                                                  [ 12%]
tests/test_backend.py .....F.....F.............                                                                                                                                       [ 41%]
tests/test_dot.py ......................                                                                                                                                              [ 67%]
tests/test_files.py ....................                                                                                                                                              [ 90%]
tests/test_lang.py ......                                                                                                                                                             [ 97%]
tests/test_tools.py ..                                                                                                                                                                [100%]

========================================================================================= FAILURES ==========================================================================================
________________________________________________________________________________________ test_render ________________________________________________________________________________________

capsys = <_pytest.capture.CaptureFixture object at 0x104115be0>, tmpdir = local('/private/tmp/pytest-of-fink-bld/pytest-9/test_render0'), engine = 'dot', format_ = 'pdf'
filename = 'hello.gv', data = b'digraph { hello -> world }'

    @pytest.exe
    def test_render(capsys, tmpdir, engine='dot', format_='pdf',
                    filename='hello.gv', data=b'digraph { hello -> world }'):
        lpath = tmpdir / filename
        lpath.write_binary(data)
        rendered = lpath.new(ext='%s.%s' % (lpath.ext, format_))
    
        assert render(engine, format_, str(lpath)) == str(rendered)
    
        assert rendered.size()
>       assert capsys.readouterr() == ('', '')
E       AssertionError: assert CaptureResult...region tag\n') == ('', '')
E         At index 1 diff: 'Fontconfig warning: ignoring UTF-8: not a valid region tag\nFontconfig warning: ignoring UTF-8: not a valid region tag\n' != ''
E         Use -v to get the full diff

tests/test_backend.py:44: AssertionError
_________________________________________________________________________________________ test_pipe _________________________________________________________________________________________

capsys = <_pytest.capture.CaptureFixture object at 0x104029c18>, svg_pattern = re.compile('(?s)^<\\?xml .+</svg>\\s*$', re.DOTALL), engine = 'dot', format_ = 'svg', data = b'graph { spam }'

    @pytest.exe
    def test_pipe(capsys, svg_pattern, engine='dot', format_='svg',
                  data=b'graph { spam }'):
        src = pipe(engine, format_, data).decode('ascii')
    
        assert svg_pattern.match(src)
>       assert capsys.readouterr() == ('', '')
E       AssertionError: assert CaptureResult...region tag\n') == ('', '')
E         At index 1 diff: 'Fontconfig warning: ignoring UTF-8: not a valid region tag\nFontconfig warning: ignoring UTF-8: not a valid region tag\n' != ''
E         Use -v to get the full diff

tests/test_backend.py:89: AssertionError

---------- coverage: platform darwin, python 3.7.0-final-0 -----------
Name                   Stmts   Miss  Cover
------------------------------------------
graphviz/__init__.py      14      0   100%
graphviz/_compat.py       39     21    46%
graphviz/backend.py       76      0   100%
graphviz/dot.py          113      0   100%
graphviz/files.py        122      0   100%
graphviz/lang.py          55      0   100%
graphviz/tools.py         17      0   100%
------------------------------------------
TOTAL                    436     21    95%
Coverage HTML written to dir htmlcov

============================================================================ 2 failed, 84 passed in 0.96 seconds ============================================================================

All tests pass on py27,34,35,36.
If I set LANG="en_US.UTF-8" , then the tests also pass with python37.

Bug with colon in name of PORT

Example

from graphviz import Digraph

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

dot.node('struct1',
            '''< 
                <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
                    <TR>
                        <TD PORT="1" ROWSPAN="2">1</TD>
                        <TD PORT="1:2" ROWSPAN="1">1:2</TD>
                    </TR>
                    <TR>
                        <TD PORT="1:3" ROWSPAN="1">1:3</TD>
                    </TR>
                </TABLE>
            >'''
)

dot.node('struct2',
            '''< 
                <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
                    <TR>
                        <TD PORT="2" ROWSPAN="2">2</TD>
                        <TD PORT="2:2" ROWSPAN="1">2:2</TD>
                    </TR>
                    <TR>
                        <TD PORT="2:3" ROWSPAN="1">2:3</TD>
                    </TR>
                </TABLE>
            >'''
)

dot.edges([('struct1:1:2', 'struct2:2:2')])



dot.view('test-output/round-table.gv')

Result

Warning: node struct1, port 1, unrecognized compass point '2' - ignored
Warning: node struct2, port 2, unrecognized compass point '2' - ignored

** (exo-open:15248): WARNING **: Couldn't connect to accessibility bus: Failed to connect to socket /tmp/dbus-UFsPtsUMtY: Connection refused

dot.source

digraph structs {
	node [shape=plaintext]
	struct1 [label=< 
                <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
                    <TR>
                        <TD PORT="1" ROWSPAN="2">1</TD>
                        <TD PORT="1:2" ROWSPAN="1">1:2</TD>
                    </TR>
                    <TR>
                        <TD PORT="1:3" ROWSPAN="1">1:3</TD>
                    </TR>
                </TABLE>
            >]
	struct2 [label=< 
                <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
                    <TR>
                        <TD PORT="2" ROWSPAN="2">2</TD>
                        <TD PORT="2:2" ROWSPAN="1">2:2</TD>
                    </TR>
                    <TR>
                        <TD PORT="2:3" ROWSPAN="1">2:3</TD>
                    </TR>
                </TABLE>
            >]
}

Image
screenshot_2018-07-09_15-26-43

Info
graphviz: 0.8.3
python: 3.6

cannot set node attributes

i was trying to get something like this in python 2.7.6
digraph G {
node [shape=circle style=filled]
...}

i found this lines :
self.node_attr = {} if graph_attr is None else dict(node_attr)

i suggest changing
import json
self.node_attr = {} if node_attr is None else json.loads(node_attr)

and when creating the Dot

dot = Digraph(comment='Some comment',format='png',node_attr='{"shape":"circle","width":"0.5"}')

i am just not sure how to add the values as it is with Dict, thanks

Option for modifying attributes of existing nodes, edges...

To modify an attribute of an existing node, the same node requires to be added again, this creates an extra line in the dot source. For many modifications, the file size of the source grows unnecessarily.
So, can there be an extra method for modifying the attributes of existing edges or nodes ( possibly removing the line from graph.body and adding a new line with the modified attribute ) ?

Add support for HTML-like labels

As stated in graphviz docs, labels can contain HTML, and those that do, should be delimited with <...>, not "..." like ordinary strings. This is impossible to achieve in the current version of this module.

Issues with Install at dot.render()

Hello,

This might be novice question, but I've been trying to test the tutorial for Python GraphViz to no avail.

I get errors when rendering the dot.render('test-output/round-table.gv', view=True) portion.

image

image

I added the following to my System Environment PATH:

C:\Program Files (x86)\Graphviz2.38\bin
C:\Program Files (x86)\Graphviz2.38\
C:\Python35\
C:\Python35\Scripts

And still the does not point to the proper files, even if I point explicitly to the file path: dot.render('c:/...test-output/round-table.gv', view=True). I get a "path too long" error.

I'm assuming that the .gv is the DOT code we save from the output code that's generated? Please correct me if I'm wrong, because the tutorial wasn't very clear on that part.

Any help will be greatly appreciated. I've been taught that half the struggle is properly setting up the environment.

Thank you!

labelfloat seems not to function

# Graph 2, pilot research
d = Digraph('Pilot Research', 'Interaction between EGA, tranSMART and GALAXY', 'E_T_G.pdf', format='pdf',node_attr={'shape': 'ellipse'})
d.node('EGA')
d.node('tranSMART')
d.node('Galaxy')
d.edge('EGA','tranSMART',label = 'mapping',labelfloat = 'true')
d.edge('EGA','Galaxy',label='processing', labelfloat = 'true')
d

It seems that 'labelfloat' doesn't work. Is there any mistake in my code?

Add format or automatic format parsing to `dot.render()`

Hi @xflr6 ,

Thanks for this library!

I would like to request adding either

  1. a new attribute format to the dot.render() function

or / and

  1. make the dot.render function automatically parse the file format from the render path.

I can submit a pull request if needed, just want to discuss this first.

The pain-point at the moment is that to save the graph, I need to either

g = Graph(format="svg")
... # Losts of code

g.render(path="figures/this_particular_figure")

or do

g.format = "svg"
g.render(path="....")

and none of these is very appealing.

Thanks!
Ge

backend.pipe doesn't work in Python 3 if the backend fails

I draw some graph and use Digraph.pipe(). If the process has some errors to say, this line will fail in Python 3.

...
  File "main.py", line 693, in render_graph
    return g.pipe()
  File "/usr/local/lib/python3.5/dist-packages/graphviz/files.py", line 103, in pipe
    outs = backend.pipe(self._engine, format, data)
  File "/usr/local/lib/python3.5/dist-packages/graphviz/backend.py", line 143, in pipe
    sys.stderr.write(errs)
TypeError: write() argument must be str, not bytes

Graph ID must starts with "cluster"

I'm new to Graphviz and this python binding. First of all, this binding works great in general.

For a cluster graph,
I noticed that if the graph ID must starts with the case-sensitive name "cluster", otherwise the output graph will become just a list of strings of all the item labels. All the styles such as shapes will be gone. Examples that work:

subg = gv.Digraph('cluster_1')

subg = gv.Digraph('cluster1')

Examples that don't work:

subg = gv.Digraph('Cluster_1')
subg = gv.Digraph('MyID')

I didn't find cautions regarding this in the DOT language reference,
so I wonder if this is a feature or a bug on the part of either the graphviz backend or the binding.

Thanks a lot!

change styles for existing DOT?

I wrote a dot_file using networkx.

Then I loaded with graphviz: dotg = graphviz.Source.from_file(dot_file)

Now I wish to change global node styles on dotg before rendering, is that possible?

Strict Graph

Hey,
I'm wondering why there is no support for the 'strict' option of graphs.
Is there reason that you don't want to implement it?
I changed it in my local library and I'm considering to commit these changes.

Thanks

Does not run in Python3

I may be missing something but it seems that this package hasn't been tested with Python 3. The module that it's failing on for me is "graphviz/lang.py"

Add support for running in MyBinder

To make it easier for potential users to demo this package, the repo can be configured so that that a pre-configured Jupyter notebook server can be launched from it and the example notebook(s) run directly using MyBinder.

Changes required:

  • add a binder directory;
  • to binder/apt.txt add the graphviz requirement;
  • to binder/requirements.txt add the . requirement to install the package from the repo root.

how to add the edge width attribute?

I understand that when adding an edge adding additional attributes is allowed. However, I think this is not working. For instance, "penweight" is the attribute to set the width of the edge. it does not work, can you help?

import graphviz as gv
g1 = gv.Digraph(format='pdf')
g1.node("A")
g1.node("B")
g1.edge("A","B", label="test",penweight="5.00")
g1.view()

Support cairo

Please support format='svg:cairo' At the moment, this results in:

ValueError: unknown format: 'svg:cairo'

AttributeError: 'module' object has no attribute 'attach'

Hi,

With 0.5 release, we have started seeing an issue which wasn't there previously.

2016-09-09 04:42:27.379963 | File "/home/jenkins/workspace/gate-kolla-python34/kolla/image/build.py", line 20, in
2016-09-09 04:42:27.379988 | import graphviz
2016-09-09 04:42:27.380044 | File "/home/jenkins/workspace/gate-kolla-python34/.tox/py34/lib/python3.4/site-packages/graphviz/init.py", line 27, in
2016-09-09 04:42:27.380066 | from .dot import Graph, Digraph
2016-09-09 04:42:27.380117 | File "/home/jenkins/workspace/gate-kolla-python34/.tox/py34/lib/python3.4/site-packages/graphviz/dot.py", line 31, in
2016-09-09 04:42:27.380144 | from . import lang, files
2016-09-09 04:42:27.380197 | File "/home/jenkins/workspace/gate-kolla-python34/.tox/py34/lib/python3.4/site-packages/graphviz/files.py", line 11, in
2016-09-09 04:42:27.380216 | from . import backend, tools
2016-09-09 04:42:27.380269 | File "/home/jenkins/workspace/gate-kolla-python34/.tox/py34/lib/python3.4/site-packages/graphviz/backend.py", line 149, in
2016-09-09 04:42:27.380292 | @tools.attach(view, 'darwin')
2016-09-09 04:42:27.380320 | AttributeError: 'module' object has no attribute 'attach'

render throws error if viewing program has lock on file

when calling g.render(view=True, cleanup=True) as i would expect a temp file is created and deleted after the viewing program is closed. However if you leave the viewing program open and it has a lock it will throw the following error:

Error: Could not open "Digraph.gv.pdf" for writing : Permission denied
---------------------------------------------------------------------------
CalledProcessError                        Traceback (most recent call last)
~\Desktop\gv_mols.py in <module>()
----> 1 showit(g)

~\Desktop\gv_mols.py in showit(g)
     67
     68 def showit(g):
---> 69         g.render(view=True,cleanup=True)
     70 showit(g)
     71 embed()

C:\Anaconda3\envs\rdkit\lib\site-packages\graphviz\files.py in render(self, filename, directory, view, cleanup)
    169         filepath = self.save(filename, directory)
    170
--> 171         rendered = backend.render(self._engine, self._format, filepath)
    172
    173         if cleanup:

C:\Anaconda3\envs\rdkit\lib\site-packages\graphviz\backend.py in render(engine, format, filepath, quiet)
    122     with open(os.devnull, 'w') as stderr:
    123         try:
--> 124             subprocess.check_call(args, startupinfo=STARTUPINFO, stderr=stderr)
    125         except OSError as e:
    126             if e.errno == errno.ENOENT:

C:\Anaconda3\envs\rdkit\lib\subprocess.py in check_call(*popenargs, **kwargs)
    289         if cmd is None:
    290             cmd = popenargs[0]
--> 291         raise CalledProcessError(retcode, cmd)
    292     return 0
    293

CalledProcessError: Command '['circo', '-Tpdf', '-O', 'Digraph.gv']' returned non-zero exit status 1.

which took me an embarrassingly long time to figure out.

It seems like (particularly with cleanup=True ) it should be able to create a unique temp file name to avoid this. I can suggest a PR if you agree.

Use pipe on stdin/stdout

'dot' accepts input on stdin and generates output on stdout when not given a filename:

$ dot -Tpng <ert.dot >ert.png

For use within an app framework it would be convenient if the graphviz library's "render" used subprocess.communicate to generate the graph, and returned a string. Then no temporary files would be required either for the graphviz source or for the generated image.

(People still might want the option for the output to be written directly to a file, e.g. if it's very large)

Clusters

Are they supported?
Are they going to be supported?

Possible Dot/Quartz Conflict... Virtualenv on a mac

I am currently running under a virtualenv with python3 and getting hte following error on a mac running sierra os...

pydotplus.graphviz.InvocationException: Program terminated with status: 1. stderr follows: Format: "iris.png" not recognized. Use one of: bmp canon cgimage cmap cmapx cmapx_np dot dot_json eps exr fig gd gd2 gif gv icns ico imap imap_np ismap jp2 jpe jpeg jpg json json0 mp pct pdf pic pict plain plain-ext png pov ps ps2 psd sgi svg svgz tga tif tiff tk vml vmlz vrml wbmp xdot xdot1.2 xdot1.4 xdot_json

If i type "dot -V" on the command line in the virtualenv i get...
dot - graphviz version 2.40.1 (20161225.0304)

when i type "which dot" i get..
/usr/local/bin/dot

When i install graphviz i use
pip install graphviz

I have read somewhere that there might be a quartz conflict and going to dot version 2.38 fixes the issue. The problem i have is that I cannot seem to install a different version of dot. When I install graphiz using..
pip install graphviz==2.38
I get that that version doesn't exist for graphviz.

Also when i try to install this
pip install pydotplus==2.38 I also get a message saying no such version, but I am unsure how else to try to get dot to change to a different version. As dot install seemed to install with either graphviz or pydotplus but neither seem to be able to change my version of dot i find in that path above...

Is there something I am missing. Virtualenv's are new to me, and mac's are not as familiar to me as centos, windows or even old Iris Linux boxes. So I am a bit new to all this, any help would be greatly appreciated!

Thanks.

graphviz fails on macOS with dyld: lazy symbol binding failed: Symbol not found: _cairo_quartz_font_face_create_for_cgfont

Hi!

Starting from yesterday graphviz has started to crash only on macOS. It can be observed with Python 2.7, 3.4, 3.6, while everything is OK with Python 3.5.

In all cases versions are the following:
graphviz: 2.40.1
python-graphviz: 0.8.3

We've investigated in this problem and found that downgrading the following python packages solves the problem:

  • fontconfig=2.12.6
  • pango=1.42.0
  • freetype=2.8

More info can be found in the upstream issue: microsoft/LightGBM#1519

Maybe you can shed some light on this.

Error log:

../../../../miniconda/envs/test-env/lib/python3.6/site-packages/graphviz/files.py:125: in pipe
    outs = backend.pipe(self._engine, format, data)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

engine = 'dot', format = 'png'
data = b'digraph {\n\tsplit0 [label="split_feature_name: Column_22\\nthreshold: 105.95000000000002\\nsplit_gain: 204.76800537...l="leaf_index: 2\\nleaf_value: -0.1745686284011742"]\n\tsplit1 -> leaf2 [label=">"]\n\tsplit0 -> split1 [label=">"]\n}'
quiet = False

    def pipe(engine, format, data, quiet=False):
        """Return ``data`` piped through Graphviz ``engine`` into ``format``.
    
        Args:
            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:
            ValueError: If ``engine`` or ``format`` are not known.
            graphviz.ExecutableNotFound: If the Graphviz executable is not found.
            subprocess.CalledProcessError: If the exit status is non-zero.
        """
        args, _ = command(engine, format)
    
        try:
            proc = subprocess.Popen(args, stdin=subprocess.PIPE,
                stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                startupinfo=STARTUPINFO)
        except OSError as e:
            if e.errno == errno.ENOENT:
                raise ExecutableNotFound(args)
            else:  # pragma: no cover
                raise
    
        outs, errs = proc.communicate(data)
        if proc.returncode:
            if not quiet:
                stderr_write_binary(errs)
                sys.stderr.flush()
>           raise subprocess.CalledProcessError(proc.returncode, args, output=outs)
E           subprocess.CalledProcessError: Command '['dot', '-Tpng']' died with <Signals.SIGABRT: 6>.

../../../../miniconda/envs/test-env/lib/python3.6/site-packages/graphviz/backend.py:166: CalledProcessError
----------------------------- Captured stderr call -----------------------------
dyld: lazy symbol binding failed: Symbol not found: _cairo_quartz_font_face_create_for_cgfont
  Referenced from: /Users/travis/miniconda/envs/test-env/lib/libpangocairo-1.0.0.dylib
  Expected in: /Users/travis/miniconda/envs/test-env/lib/libcairo.2.dylib

dyld: Symbol not found: _cairo_quartz_font_face_create_for_cgfont
  Referenced from: /Users/travis/miniconda/envs/test-env/lib/libpangocairo-1.0.0.dylib
  Expected in: /Users/travis/miniconda/envs/test-env/lib/libcairo.2.dylib

Incorrect indentation in generated file

This is all tested with the graphviz python package in version 0.7.1, which is currently the latest.

Here is a test script

#!/usr/bin/env python2

import graphviz

graph = graphviz.Graph()
graph.edge("a", "b")
subgraph = graphviz.Graph(body=["rank=same"])
subgraph.node("sub", label="hero")
subgraph.edge("sub", "zero")
graph.subgraph(subgraph)
graph.edge("a", "sub")
graph.edge("b", "zero")

print graph

which generates the following output

graph {
                a -- b
        {
        rank=same
                sub [label=hero]
                        sub -- zero
        }
                a -- sub
                b -- zero
}

We can see that some lines are incorrectly indented: in this case the edge lines and the rank line.

What we expect in this case is the following

graph {
        a -- b
        {
                rank=same
                sub [label=hero]
                sub -- zero
        }
        a -- sub
        b -- zero
}

Here is the graph, as rendered by dot, for completeness:

graphvizbadindent

Is there any API to convert a gv.Graph object to numpy.ndarray?

I need to generate network topo image and handle it immediately. So, saving a gv.Graph object to png image file and reading it by PIL.Image is wasting time. And could anyone tell me any method to convert a gv.Graph object to numpy.ndarray object in memory but not on hard-disk?

SVG rendering in Jupyterlab doens't work for Firefox

I noticed that the SVG graphs wouldn't render properly in Jupyterlab under Firefox.

Some investigation and testing revealed that the svg+xml returned by the built-in _repr_svg_ methods does not URL encode the # characters. This is apparently something that is required by the specifications, although Firefox seems to be the only one refusing to render the data. (See https://stackoverflow.com/questions/30733607/svg-data-image-not-working-on-firefox?answertab=active#tab-top for reference)

Adding a simple .replace('#', '%23') to the output of _repr_svg_ seems to resolve the problem, although there might be a more elegant solution that I'm not aware of.

Cannot extend existing class by inherintance when using subgraph

Graph.subgraph and Digraph.subgraph have a very strict checking for class type which makes it impossible to extend existing class by inheritance.

For example, I have the following class definition:

class ClusterGraph(Graph):
    def __init__(self, name):
        Graph.__init__("cluster_"+name)

g1 = Graph()
g2 = ClusterGraph()
g1.subgraph(g2) # will fail because of the strict type checking.

syntax error in centos6.7

windows: dot - graphviz version 2.38.0 (20140413.2041) graphviz (0.10.1)
It return the correct result.
centos6.7: dot - graphviz version 2.26.0 (20091210.2329) graphviz (0.10.1)
It cause the syntax error.
The code is the same.I use python 3.5.Is it a bug? Thank you.

My code:

from graphviz import Digraph
import os
#os.environ["PATH"] += os.pathsep + 'C:/Program Files (x86)/Graphviz2.38/bin/'
dot = Digraph(comment='The Test Table',format='png')
dot.attr(rankdir='LR')
dot.node('A', u'zeus \n信息资源申请',fontname="SimSun",color='green', style='filled')
dot.node('B', u'jason \n部门负责人审批 ',fontname="SimSun",shape='diamond',color='lightblue2', style='filled')
dot.node('C', u'alex \n中心负责人审批',fontname="SimSun",shape='diamond',color='lightblue2', style='filled')
dot.node('D', u'zeus \n申请人确认',fontname="SimSun",shape='diamond',color='lightblue2', style='filled')
dot.node('E', u'归档',fontname="SimSun",color='green', style='filled')
dot.edges(['AB', 'BC','CD','DE'])
dot.edge('B', 'A', u'驳回',fontname="SimSun")
dot.edge('C', 'A', u'驳回',fontname="SimSun")
print(dot.source)
dot.render('test-output/test-table.gv', view=False)
#view=True 自动打开

In windows is ok,but in centos6.7 it cause error.The error is:

// The Test Table
digraph {
rankdir=LR
A [label="zeus
信息资源申请" color=green fontname=SimSun style=filled]
B [label="jason
部门负责人审批 " color=lightblue2 fontname=SimSun shape=diamond style=filled]
C [label="alex
中心负责人审批" color=lightblue2 fontname=SimSun shape=diamond style=filled]
D [label="zeus
申请人确认" color=lightblue2 fontname=SimSun shape=diamond style=filled]
E [label="归档" color=green fontname=SimSun style=filled]
A -> B
B -> C
C -> D
D -> E
B -> A [label="驳回" fontname=SimSun]
C -> A [label="驳回" fontname=SimSun]
}
Warning: test-output/test-table.gv:4: string ran past end of line
Warning: test-output/test-table.gv:5: string ran past end of line
Error: test-output/test-table.gv:6: syntax error near line 6
context: B >>> [ <<< label="jason
Warning: test-output/test-table.gv:6: string ran past end of line
Warning: test-output/test-table.gv:7: string ran past end of line
Warning: test-output/test-table.gv:8: string ran past end of line
Warning: test-output/test-table.gv:9: string ran past end of line
Warning: test-output/test-table.gv:10: string ran past end of line
Warning: test-output/test-table.gv:11: string ran past end of line
Traceback (most recent call last):
File "test_graphviz.py", line 46, in
dot.render('test-output/test-table.gv', view=False)
File "/opt/py35env/lib/python3.5/site-packages/graphviz/files.py", line 188, in render
rendered = backend.render(self._engine, format, filepath, renderer, formatter)
File "/opt/py35env/lib/python3.5/site-packages/graphviz/backend.py", line 183, in render
run(cmd, capture_output=True, check=True, quiet=quiet)
File "/opt/py35env/lib/python3.5/site-packages/graphviz/backend.py", line 159, in run
raise CalledProcessError(proc.returncode, cmd, output=out, stderr=err)
subprocess.CalledProcessError: Command '['dot', '-Tpng', '-O', 'test-output/test-table.gv']' returned non-zero exit status 1

what's wrong with me? Please help me .Thanks..

Finding `dot` fails for conda install of `graphviz` on Windows

Installing the python-graphviz conda package also fetches the graphviz conda package. On Windows, graphviz binaries are put into Library/bin/graphviz, and dot.bat etc. is put in Library/bin, which is on PATH. However, .bat files are not automatically recognized for execution by subprocess.Popen, which causes the engine execution to fail:

RuntimeError: failed to execute ['dot', '-Tsvg'], make sure the Graphviz executables are on your systems' path

A specific fix for this could be to try to launch the engine with a .bat postfix if Popen fails on Windows.

A more general strategy on Windows could be to iterate over all extensions in os.environ['PathExt'] and attempt those.

A third option would be to allow the engine argument to be specified with a file extension, i.e. the extension is stripped with os.path.splitext(engine)[0] before validating against ENGINES. This would place more of a burden on the user, but it also gives the user more control.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.