2014-07-16 11 views
5

mi piacerebbe chiamare "Converti" utilità dal ImageMagick dal mio script Python utilizzando Popen, in questo modo:Popen con eseguibile in conflitto/percorso

Popen(["convert", input_path, "-flop", output_file_path]) 

(L'esempio precedente inverte semplicemente l'immagine in senso orizzontale)

Il problema è che quando eseguo lo script in Windows, per errore chiama l'utilità convert.exe fornita con Windows per convertire le partizioni FAT in NTFS! (situato in \ Windows \ system32)

Ora, se apro un prompt dei comandi in una directory diversa da system32 e digito "convert", esegue correttamente l'eseguibile ImageMagick. Quindi, questo implica che Popen stia cercando automaticamente in system32. Come posso farlo sembrare non in system32 ed eseguire l'eseguibile corretto?

+0

Hai provato a rimuovere il percorso da system32 da 'sys.path'? –

+1

i) system32 non è in 'sys.path' ii)' Popen' non appare in 'sys.path'. – Daniel

+0

'Popen' inizia dalla directory corrente. Qual è la tua variabile di ambiente 'PATH'? – Daniel

risposta

7

Cercare un programma non è banale. Vorrei specificare il percorso completo dell'eseguibile convert.exe in modo esplicito.

subprocess utilizza CreateProcess on Windows that looks in system32 directory even before any other directory in %PATH%:

... Se il nome del file non contiene un'estensione, .exe è allegato. Pertanto, se l'estensione del nome file è .com, questo parametro deve includere l'estensione .com. Se il nome del file termina in un punto (.) Con senza estensione, o se il nome del file contiene un percorso, .exe non è aggiunto. Se il nome del file non contiene un percorso di directory, il sistema cerca il file eseguibile nel seguente ordine:

  1. La directory da cui l'applicazione caricata.
  2. La directory corrente per il processo padre.
  3. Directory di sistema Windows a 32 bit. Utilizzare la funzione GetSystemDirectory per ottenere il percorso di questa directory.
  4. Directory di sistema Windows a 16 bit. Non esiste una funzione che ottenga il percorso di questa directory, ma viene cercata. Il nome di questa directory è System.
  5. La directory di Windows. Utilizzare la funzione GetWindowsDirectory per ottenere il percorso di questa directory.
  6. Le directory elencate nella variabile di ambiente PATH. Si noti che questa funzione non ricerca il percorso per applicazione specificato dalla chiave di registro App Paths. Per includere questo percorso per applicazione nella sequenza di ricerca, utilizzare la funzione ShellExecute.

Pertanto convert equivale a convert.exe in questo caso. Per prima cosa viene visualizzata una directory contenente sys.executable ad es., C:\Python27. Quindi nella directory corrente: da dove hai iniziato lo script Python. Quindi in system32 dove trova convert.exe (utilità di file system, non imagemagick).

Si potrebbe provare a rimuovere la directory system32 da os.environ['PATH'] potrebbe (?) Sopprimerlo controllandolo: Popen(cmd, env=no_system32_environ) ma è fragile (peggio del percorso esplicito).

C'è un problema correlato su Python bug tracker: "Subprocess picks the wrong executable on Windows."


cmd.exe (il guscio) utilizza algoritmo diverso. Vedere How does Windows locate files input in the shell?

Se si imposta shell=True allora la sequenza di ricerca per convert programma:

  1. convert non è un comando interno di shell
  2. non v'è alcun percorso esplicito, quindi la ricerca continua
  3. cercare la corrente directory
  4. cercare ogni directory specificata dalla variabile di ambiente PATH, nell'ordine elencato

%PATHEXT% definisce quali estensioni di file vengono controllate e in quale ordine, ad esempio, convert.com, convert.exe, convert.bat, convert.cmd se %PATHEXT% è .com;.exe;.bat;.cmd.

+1

FYI, in Vista e successivamente sia 'CreateProcess' che la funzione' SearchForExecutable' nella chiamata cmd.exe ['NeedCurrentDirectoryForExePath'] (https://msdn.microsoft.com/en-us/library/ms684269). Se imposti la variabile di ambiente 'NoDefaultCurrentDirectoryInExePath' impedisce la ricerca nella directory corrente. – eryksun

+1

Si potrebbe anche notare che, dopo aver trovato il file, cmd.exe prova prima 'CreateProcess' (indipendentemente dall'estensione del file) e quindi prova' ShellExecuteEx', che consente l'esecuzione di tipi di file arbitrari. il comando 'start' di cmd è simile ma chiama' ShellExecuteEx' anche se non viene trovato alcun file, come per i comandi registrati 'App Paths' (ad esempio' start/b/w python.exe' dovrebbe funzionare anche se python.exe non è trovato, dal momento che il programma di installazione deve aver registrato un comando predefinito per "python.exe"). – eryksun

2

Come approccio completamente diverso, si consiglia di provare PythonMagick, un wrapper Python per ImageMagick. In questo modo è possibile accedere alle funzioni di convert all'interno di Python e non sarà necessario generare processi esterni.

0

Mi sono imbattuto in questo. L'esecuzione di uno script php in una shell ha accesso alla shell $ PATH, mentre l'esecuzione all'interno di Apache non lo fa (almeno non un $ PATH con Cygwin dll/exe).

In secondo luogo, utilizzare la notazione nativa di Windows C:/dir/subdir/pgm in php su una piattaforma Windows e otterrete ciò che vi aspettate.

Quindi il codice multi-piattaforma deve cambiare/virare il percorso e quindi fare riferimento alla decisione.