Pietro Speroni
Pietro Speroni

Reputation: 3231

How do I run "dot" as a command from Python?

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?

Upvotes: 6

Views: 10661

Answers (12)

mjp
mjp

Reputation: 1689

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.

Upvotes: 0

GEOCHET
GEOCHET

Reputation: 21323

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.

Upvotes: 3

retracile
retracile

Reputation: 12349

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.

Upvotes: 1

Schnouki
Schnouki

Reputation: 7717

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.

Upvotes: 1

Peter Stuifzand
Peter Stuifzand

Reputation: 5104

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

Upvotes: 2

Petriborg
Petriborg

Reputation: 2960

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.

Upvotes: 2

uolot
uolot

Reputation: 1460

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.

Upvotes: 1

lmount
lmount

Reputation: 1302

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

Upvotes: 2

wr.
wr.

Reputation: 2857

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')

Upvotes: 2

codeape
codeape

Reputation: 100914

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.

Upvotes: 2

alxp
alxp

Reputation: 6341

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

Upvotes: 3

laalto
laalto

Reputation: 152927

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

Upvotes: 10

Related Questions