Come posso eseguire "punto" come comando da Python?
Domanda
Sto usando Python su Mac OSX Leopard.
Sto cercando di eseguire il programma 'dot' (parte di Graphviz) da 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")
Il comando "ls" è lì solo per assicurarsi che Python sia nella directory corretta.È.Il risultato che ottengo è:
/usr/bin:/bin:/usr/sbin:/sbin 0 32512
Da quanto ho capito, l'errore 32512 significa che Python non è riuscito a trovare il file e poiché il file 6.dot è presente (se eseguo "dot -o9.png -Tpng ./6.dot" dal terminale non ricevo alcun errore, e 9.png viene prodotto), presumo che Python non riesca a trovare il file punto.
Probabilmente devo aggiungere il file punto al percorso.Ma non so dov'è.Se corro:
whereis dot
Non ricevo risposta.
Come posso trovare l'eseguibile punto?
In alternativa, posso eseguire il programma punto come comando dall'interno di Python?
Soluzione
Si dovrebbe modificare la riga PATH in modo che includa la directory che contiene dot
. Questo elenco è /usr/local/bin
senza /dot
.
Altri suggerimenti
whereis
individua le pagine man, which
individua i binari. Quindi provare which dot
.
È necessario aggiungere il percorso del file eseguibile 'dot' in un ambiente Python. È possibile farlo modificando la variabile PATH in os.environ
Prova questo:
# -*- 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"])
Preso dalla questione per cercare di mantenere una sorta di sanità mentale qui.
Risoluzione dei problemi:
A. aggiungi
print os.getcwd()
sulla linea prima os.system ( "Dot ecc.
Solo per fare in modo che la directory corrente è quella con il file 6.dot
.
B. Assicurarsi che il programma dot
è nel tuo percorso.
which dot
C. Utilizzare il percorso completo del programma dot
nel comando os.system, vedere cosa succede poi.
Se anche si generano i file Dot in Python, pydot fa ciò che vuoi in un modo più Pythonic:
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')
Spesso la soluzione è davanti a noi,
print os.system("/usr/local/bin/dot -o9.png -Tpng 6.dot")
Inoltre puoi provare tutti i punti in una cartella specificata
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)
Modificare:
Comunque non riesco a ricordare se lo è
/usr/local/bin/dot -o9.png -Tpng fdot.dot
O
/usr/local/bin/dot -o 9.png -Tpng fdot.dot
Due suggerimenti
- Non utilizzare PATH, invece usare "che" per trovare solo l'eseguibile invece
- Non si utilizza ";" (Punto e virgola) per percorsi separati, ma ":" (due punti). Una volta che si cambia questa dovrebbe essere in grado di trovare il vostro programma di punti.
Modificare questo
os.environ['PATH'] += ";"+"/usr/local/bin/dot"
a questo
os.environ['PATH'] += ":"+"/usr/local/bin"
Quindi il vostro bene.
EDIT: Si noti che ho dimenticato di rimuovere il / punti dalla variabile PATH me (oops) - PATH è un elenco delimitato da due punti di directory
.Al posto di:
print os.system("dot -o9.png -Tpng ./6.dot")
provare questo:
from subprocess import check_call
print check_call("dot -o9.png -Tpng ./6.dot")
Se lo stato di uscita del programma di punto è 0, lo stato viene stampato. Se dot ritorna stato diverso da zero, solleva CalledProcessError (e spettacoli restituito di stato). Se dot non esiste nel percorso corrente, OSError è sollevata su Linux o su Windows WindowsErroor (non so quale viene sollevata un'eccezione in Mac OS, ma suppongo OSError).
EDIT: Codice sopra vi darà il suggerimento se non avete eseguibile o un file dot 6.dot in impostazioni del percorso attuale
. check_call
non usa la stessa sintassi os.system
, così si dovrebbe provare a cambiare la riga corrispondente in questo modo:
print check_call(["dot", "-o9.png", "-Tpng", "./6.dot"])
Il nome eseguibile è il primo elemento dell'array, e ogni parametro deve essere in un altro elemento della matrice. Altrimenti si sempre ottiene un "No such file" errore perché non c'è eseguibile chiamato "dot -o9.png ..." nel PATH.
Un problema è in questa linea:
os.environ['PATH'] += ":"+"/usr/local/bin/dot"
non mettere il nome del file eseguibile nel percorso, ma la directory contenente il file eseguibile. In modo che dovrebbe essere:
os.environ['PATH'] += ":"+"/usr/local/bin"
E come sottolineato in un altro commento, gli argomenti a check_call
non sono le stesse di os.system
.
Se si utilizza una GUI, come Spyder
allora si può semplicemente aggiungere il percorso bin corretto nel menu delle opzioni PYTHONPATH manager
.
Cerca l'ubicazione dello script facendo questo nel terminale:
which programname
poi prendere quella posizione (ovunque essa sia), sottrarre il ProgramName, ad esempio:
/home/username/seiscomp3/bin/scart
#this is the section of the path that you use
/home/username/seiscomp3/bin
Poi vai nel menu delle opzioni PYTHONPATH manager
e aggiungere questo percorso. Quindi riavviare Spyder e funzionerà.