6

I am using Python on Mac OSX Leopard.

I am trying to run the program 'dot' (part of Graphviz) from Python:

# -*- coding: utf-8 -*-
import os

print os.environ['PATH']
print os.system("ls >> a.txt")
print os.system("dot -o9.png -Tpng ./6.dot")

The command "ls" is there just to make sure that python is in the correct directory. It is. The result that I get is:

/usr/bin:/bin:/usr/sbin:/sbin 0 32512

My understanding is that 32512 error means that python could not find the file, and since the file 6.dot is there (If I run "dot -o9.png -Tpng ./6.dot" from the terminal I receive no error, and 9.png gets produced), I assume Python can't find the dot file.

I probably need to add the dot file to the path. But I don't know where is it. If I run:

whereis dot

I receive no answer.

How can I find the dot executable?
Alternatively, can I run the dot program as a command from inside Python?

7
  • 2
    Could you please format your question in a more readable way? Thanks! Commented Jun 5, 2009 at 11:57
  • Do you run your Python script in the directory that contains 6.dot? Commented Jun 5, 2009 at 11:59
  • 1
    You really ought to put the code that worked into an answer and accept it. Commented Jun 5, 2009 at 15:13
  • 2
    This doesn't seem like it should be a CW. Is there something I'm missing that makes this a CW-worthy question? Commented Jun 5, 2009 at 15:18
  • 1
    @Rich: GAH!! MY EYES! This is a poster child for good and bad editing. Commented Jun 5, 2009 at 15:23

12 Answers 12

10

whereis locates man pages, which locates binaries. So try which dot.

Sign up to request clarification or add additional context in comments.

Comments

3

You need to add the path to the 'dot' executable in Python's environment. You can do this by modifying the PATH variable in os.environ

Comments

3

Try this:

# -*- coding: utf-8 -*-
import os
import sys

print os.environ['PATH']

os.environ['PATH'] += ":"+"/usr/local/bin"
print os.environ['PATH']

print os.getcwd()

from subprocess import check_call
print check_call(["dot", "-o9.png", "-Tpng", "./6.dot"])

Taken from the question to try and maintain some sort of sanity here.

4 Comments

It's far too late to talk of sanity. Let's talk instead of the bigger issue: how can (and should) SO be improved to handle troubleshooting conversations?
@Pesto: It wouldn't be necessary if authors wouldn't sit there and troubleshoot on SO. They should be asking one question, and when that issues is resolved, asking a new one. This kind of stuff is bred from OPs who simply refuse to understand what SO is for and how it works.
@Rich, @Pesto: The solution is simpler. For some reason Firefox is not letting me comment, vote, chose an answer or open the WYSIWYG edit program. Without all this everything I write looks horrible, I cannot give feedback, and add details. In short I am forced to edit back the question area, and add the new material there. Now I am able to comment as I am using a different browser. And Rich has a bias against what I do here, so he immediately assumes bad faith.
@Pietro: Stop disabling Javascript.
2

You should change the PATH line so it includes the directory which contains dot. That directory is /usr/local/bin, without /dot.

Comments

2

Troubleshooting tips:

A. add

print os.getcwd()

on the line before os.system("dot etc.

Just to make sure that the current directory is the one with the 6.dot file.

B. Make sure that the dot program is in your path.

which dot

C. Use the full path to the dot program in your os.system command, see what happens then.

Comments

2

If you also generate your Dot files in Python, pydot does what you want in a more Pythonic way:

import pydot
dot = pydot.Dot()
n1, n2 = pydot.Node("a"), pydot.Node("b")
dot.add_node(n1)
dot.add_node(n2)
dot.add_edge(pydot.Edge(n1,n2))
dot.write_png("graph.png", prog='neato')

1 Comment

This might be the right place to mention the python-graph library (code.google.com/p/python-graph) which wraps pydot.
2

Often the solution is in front of us,

print os.system("/usr/local/bin/dot -o9.png -Tpng 6.dot")

Also you can try for all the dots in a specified folder

import glob
for filedot in glob.glob('*.dot')
    print os.system("/usr/local/bin/dot -o9.png -Tpng %(filedot)s"%locals())
    #print os.system("/usr/local/bin/dot -o9.png -Tpng %s"%filedot)

Edit:

I cannot recall btw if it is

/usr/local/bin/dot -o9.png -Tpng fdot.dot

or

/usr/local/bin/dot -o 9.png -Tpng fdot.dot

Comments

2

Two suggestions

  1. Don't use PATH, instead use "which" to just find the executable instead
  2. You don't use ";" (semi-colon) to separate paths, but ":" (colon). Once you change this it should be able to find your dot program.

Change this

os.environ['PATH'] += ";"+"/usr/local/bin/dot"

to this

os.environ['PATH'] += ":"+"/usr/local/bin"

Then your good.

EDIT: Note that I forgot to remove the /dot from the PATH variable myself (oops) - PATH is a colon delimited list of directories.

Comments

1

Instead of:

print os.system("dot -o9.png -Tpng ./6.dot")

try this:

from subprocess import check_call
print check_call("dot -o9.png -Tpng ./6.dot")

If exit status of dot program is 0, the status is printed. If dot returns non-zero status, it raises CalledProcessError (and shows returned status). If dot doesn't exist in current path, OSError is raised on Linux or WindowsErroor on Windows (I don't know which exception is raised under Mac OS, but I assume OSError).

EDIT: Code above will give you the hint if you have no dot executable or 6.dot file in current path settings.

Comments

1

check_call does not use the same syntax as os.system, so you should try changing the corresponding line this way:

print check_call(["dot", "-o9.png", "-Tpng", "./6.dot"])

The executable name is the first item in the array, and each parameter must be in another item of the array. Otherwise you will always get a "No such file" error because there is no executable named "dot -o9.png ..." in your PATH.

Comments

1

One problem is in this line:

os.environ['PATH'] += ":"+"/usr/local/bin/dot"

You don't put the name of the executable in the path, but the directory containing the executable. So that should be:

os.environ['PATH'] += ":"+"/usr/local/bin"

And as pointed out in another comment, the arguments to check_call are not the same as os.system.

1 Comment

Thanks, this was actually part of the solution.
0

If you are using a GUI such as Spyder then you can simply add the correct bin path into the PYTHONPATH manager options menu.

Search for the script location by doing this in the terminal:

which programname

then take that location (wherever it is), subtract the programname, for example:

/home/username/seiscomp3/bin/scart
#this is the section of the path that you use
/home/username/seiscomp3/bin

Then go into the PYTHONPATH manager options menu and add this path. Then restart Spyder and it'll work.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.