Come eseguo un programma da Python? os.system non riesce a causa di spazi nel percorso


273

Ho uno script Python che deve eseguire un programma esterno, ma per qualche ragione fallisce.

Se ho il seguente script:

import os;
os.system("C:\\Temp\\a b c\\Notepad.exe");
raw_input();

Quindi non riesce con il seguente errore:

'C: \ Temp \ a' non è riconosciuto come comando interno o esterno, programma eseguibile o file batch.

Se sfuggo al programma con le virgolette:

import os;
os.system('"C:\\Temp\\a b c\\Notepad.exe"');
raw_input();

Quindi funziona. Tuttavia, se aggiungo un parametro, smette di funzionare di nuovo:

import os;
os.system('"C:\\Temp\\a b c\\Notepad.exe" "C:\\test.txt"');
raw_input();

Qual è il modo giusto per eseguire un programma e attendere che venga completato? Non ho bisogno di leggere l'output da esso, poiché è un programma visivo che fa un lavoro e poi esce, ma devo aspettare che venga completato.

Nota anche che lo spostamento del programma su un percorso non spaziato non è un'opzione.


Questo non funziona neanche:

import os;
os.system("'C:\\Temp\\a b c\\Notepad.exe'");
raw_input();

Nota le virgolette singole / doppie scambiate.

Con o senza un parametro per Blocco note qui, non riesce con il messaggio di errore

La sintassi del nome file, della directory o dell'etichetta del volume non è corretta.


Usa questo: os.system(r'C:\temp\"a b c"\Notepad.exe') o questo:os.system('C:\\temp\\"a b c"\\Notepad.exe')
chanzerre l'

Per i visitatori futuri, se si desidera eseguire un'app con argomenti (utilizzando il sottoprocesso). devi dividere i tuoi argomenti per spazio e passarli singolarmente. Ad esempio, questo è da un file bat: "C:\Program Files\GDAL\gdal_translate.exe" -ot byte -of GTIFF -scale -co PHOTOMETRIC=CMYK "cmyk-16.tif" "cmyk-8_out.tif". In Python, diventa: ["C:\\Program Files\\GDAL\\gdal_translate.exe", "-ot", "byte", "-scale", "-co", "PHOTOMETRIC=CMYK", "input_cmyk-16.tif", "output_cmyk-8.tif"].
akinuri,

Risposte:


297

subprocess.calleviterà problemi nel dover trattare convenzioni di quotazione di varie shell. Accetta un elenco, anziché una stringa, quindi gli argomenti vengono delimitati più facilmente. vale a dire

import subprocess
subprocess.call(['C:\\Temp\\a b c\\Notepad.exe', 'C:\\test.txt'])

81
È molto più semplice utilizzare la stringa non
elaborata

1
Sì, le funzioni os.exec * sostituiranno il processo corrente, quindi il processo python non continuerà. Sono usati più su unix dove il metodo generale per una shell per lanciare un comando è fork () e quindi exec () nel figlio.
Brian,

1
Il metodo windows per questo è la famiglia os.spawn, che potrebbe essere usata invece. il sottoprocesso è tuttavia più portatile e offre una maggiore flessibilità nel controllo del processo (acquisizione di input / output, ecc.), quindi è preferibile.
Brian,

6
@PierreBdr: c'è un caso in cui i rawstring non funzionano: dove hai bisogno di una barra finale. ad es. r'c: \ foo \ bar \ '. In realtà, è probabilmente meglio usare invece le barre in avanti. Questi sono accettati in tutta l'API di Windows (anche se non sempre da alcuni comandi di shell (es. Copia))
Brian

1
Per python> = 3.5 subprocess.calldovrebbe essere sostituito da subprocess.run docs.python.org/3/library/subprocess.html#older-high-level-api
gbonetti

67

Ecco un modo diverso di farlo.

Se stai usando Windows, il seguente si comporta come un doppio clic sul file in Esplora risorse o dando il nome del file come argomento al comando "start" del DOS: il file viene aperto con qualsiasi applicazione (se presente) alla quale è associata l'estensione .

filepath = 'textfile.txt'
import os
os.startfile(filepath)

Esempio:

import os
os.startfile('textfile.txt')

Questo aprirà textfile.txt con Blocco note se Blocco note è associato ai file .txt.


1
Esiste una funzione equivalente per i sistemi * nix?
Romeno,

@Romeno: potresti provare: webbrowser.open("textfile.txt")dovrebbe aprire un editor di testo. Vedi anche "avviare il secondo programma da solo, come se avessi semplicemente fatto doppio clic su di esso".
jfs,

Nella mia configurazione textfile.txt deve essere tra virgolette, ad esempio:os.startfile('path\to\textfile.txt')
thdoan

34

Le citazioni più esterne sono consumate dallo stesso Python e la shell di Windows non lo vede. Come accennato in precedenza, Windows comprende solo le virgolette. Python converte la barra rovesciata in barre rovesciate su Windows, quindi puoi usarla

os.system('"C://Temp/a b c/Notepad.exe"')

Il 'è consumato da Python, che quindi passa "C: //Temp/abc/Notepad.exe" (come percorso Windows, non sono necessarie doppie barre rovesciate) a CMD.EXE


1
Questo sembra il migliore in uno scenario come quello in os.system('curl URL > file')cui voglio vedere l'aggiornamento dell'indicatore di progresso di cURL per file di grandi dimensioni.
Zach Young,

Se la prima lettera dopo una barra rovesciata ha un significato speciale (cioè \t, \necc), allora quel particolare backslash deve essere raddoppiata. Essere un percorso di Windows non ha nulla a che fare con esso.
Ethan Furman,

1
Si noti che se si utilizza os.system()su Windows la finestra cmd si aprirà e rimarrà aperta fino alla chiusura del processo avviato. IMHO è meglio usare os.startfile().
thdoan,

1
Non dimenticareimport os
Besi,


19

Almeno in Windows 7 e Python 3.1, os.systemin Windows la virgoletta deve essere racchiusa tra virgolette se ci sono spazi nel percorso del comando. Per esempio:

  TheCommand = '\"\"C:\\Temp\\a b c\\Notepad.exe\"\"'
  os.system(TheCommand)

Un esempio del mondo reale che mi stordiva era la clonazione di un'unità in VirtualBox. La subprocess.callsoluzione sopra non ha funzionato a causa di alcuni problemi con i diritti di accesso, ma quando ho citato due volte il comando, sono os.systemdiventato felice:

  TheCommand = '\"\"C:\\Program Files\\Sun\\VirtualBox\\VBoxManage.exe\" ' \
                 + ' clonehd \"' + OrigFile + '\" \"' + NewFile + '\"\"'
  os.system(TheCommand)

Questo è stato! Vorrei subprocess, ma a volte os.systeme os.popen(...).read()sono solo più veloce da scrivere. A proposito, non è necessario sfuggire alle doppie virgolette all'interno del singolo, cioè '""C:\\Temp\\a b c\\Notepad.exe""'lo farà.
Tomasz Gandor,

9
import win32api # if active state python is installed or install pywin32 package seperately

try: win32api.WinExec('NOTEPAD.exe') # Works seamlessly
except: pass

e sembra che non sia necessaria alcuna citazione con questo metodo, ad esempio win32api.WinExec ('pythonw.exe d: \ web2py \ web2py.py -K welcome') avvia lo scheduler web2py in background.
Tim Richardson,

@rahul e fa eccezione per gli argomenti per l'eseguibile? Quindi se vuoi che Blocco note apra un file o è separato?
sayth


3

Ho il sospetto che sia lo stesso problema di quando usi le scorciatoie in Windows ... Prova questo:

import os;
os.system("\"C:\\Temp\\a b c\\Notepad.exe\" C:\\test.txt");

scusa, neanche questo funziona, domanda modificata per riflettere questo.
Lasse V. Karlsen,

Penso che Windows usi solo ", piuttosto che" per la quotazione. Probabilmente funzionerà se lo cambi. Tuttavia, avrai comunque problemi con le citazioni incorporate, ecc.
Brian,

Ho pensato che ci fossero voluti entrambi, ma probabilmente hai ragione. So che funziona (nel guscio almeno) con virgolette doppie.
Matthew Scharley,

+1 questo è il migliore, Windows XP, edizione Home 2007 ha funzionato bene

0

Supponiamo di voler eseguire il tuo server web Django (in Linux) che ci sia spazio tra il tuo percorso (path = '/home/<you>/<first-path-section> <second-path-section>'), quindi procedi come segue:

import subprocess

args = ['{}/manage.py'.format('/home/<you>/<first-path-section> <second-path-section>'), 'runserver']
res = subprocess.Popen(args, stdout=subprocess.PIPE)
output, error_ = res.communicate()

if not error_:
    print(output)
else:
    print(error_)

[ Nota ]:

  • Non dimenticare di accedere all'autorizzazione: chmod 755 -R <'yor path'>
  • manage.py è eccezionale: chmod +x manage.py

0

Per Python 3.7, utilizzare subprocess.call . Usa una stringa non elaborata per semplificare i percorsi di Windows:

import subprocess
subprocess.call([r'C:\Temp\Example\Notepad.exe', 'C:\test.txt'])

0

Non necessita di sottoprocessi, può essere semplicemente raggiunto da

GitPath = "C: \ Programmi \ Git \ git-bash.exe" # Percorso del file dell'applicazione in mycase relativo file GITBASH os.start (GitPath)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.