Wie führe ich ein Programm aus Python aus? os.system schlägt aufgrund von Leerzeichen im Pfad fehl

273

Ich habe ein Python-Skript, das ein externes Programm ausführen muss, aber aus irgendeinem Grund fehlschlägt.

Wenn ich folgendes Skript habe:

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

Dann schlägt es mit folgendem Fehler fehl:

'C: \ Temp \ a' wird nicht als interner oder externer Befehl, bedienbares Programm oder Batchdatei erkannt.

Wenn ich dem Programm mit Anführungszeichen entkomme:

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

Dann funktioniert es. Wenn ich jedoch einen Parameter hinzufüge, funktioniert er nicht mehr:

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

Was ist der richtige Weg, um ein Programm auszuführen und auf dessen Abschluss zu warten? Ich muss die Ausgabe nicht lesen, da es sich um ein visuelles Programm handelt, das einen Job erledigt und dann einfach beendet wird, aber ich muss warten, bis es abgeschlossen ist.

Beachten Sie auch, dass das Verschieben des Programms in einen Pfad ohne Abstand ebenfalls keine Option ist.


Dies funktioniert auch nicht:

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

Beachten Sie die vertauschten einfachen / doppelten Anführungszeichen.

Mit oder ohne Parameter für Notepad schlägt hier die Fehlermeldung fehl

Die Syntax für Dateiname, Verzeichnisname oder Datenträgerbezeichnung ist falsch.

Lasse V. Karlsen
quelle
Verwenden Sie dies: os.system(r'C:\temp\"a b c"\Notepad.exe') oder dies:os.system('C:\\temp\\"a b c"\\Notepad.exe')
Chanzerre
Für zukünftige Besucher, wenn Sie eine App mit Argumenten ausführen möchten (mithilfe eines Unterprozesses). Sie müssen Ihre Argumente nach Leerzeichen aufteilen und jedes einzeln übergeben. Dies stammt beispielsweise aus einer Fledermausdatei : "C:\Program Files\GDAL\gdal_translate.exe" -ot byte -of GTIFF -scale -co PHOTOMETRIC=CMYK "cmyk-16.tif" "cmyk-8_out.tif". In Python wird es : ["C:\\Program Files\\GDAL\\gdal_translate.exe", "-ot", "byte", "-scale", "-co", "PHOTOMETRIC=CMYK", "input_cmyk-16.tif", "output_cmyk-8.tif"].
Akinuri

Antworten:

297

subprocess.callvermeidet Probleme mit dem Zitieren von Konventionen verschiedener Schalen. Es akzeptiert eine Liste anstelle einer Zeichenfolge, sodass Argumente leichter abgegrenzt werden können. dh

import subprocess
subprocess.call(['C:\\Temp\\a b c\\Notepad.exe', 'C:\\test.txt'])
Brian
quelle
81
Es ist viel einfacher, rohe Zeichenfolgen in Windows zu verwenden: r "C: \ Temp \ abc \ Notepad.exe"
PierreBdR
1
Ja, die Funktionen von os.exec * ersetzen den aktuellen Prozess, sodass Ihr Python-Prozess nicht fortgesetzt wird. Sie werden eher unter Unix verwendet, wo die allgemeine Methode für eine Shell zum Starten eines Befehls darin besteht, das untergeordnete Element zu fork () und dann exec ().
Brian
1
Die Windows-Methode hierfür ist die os.spawn-Familie, die stattdessen verwendet werden könnte. Der Unterprozess ist jedoch portabler und bietet mehr Flexibilität bei der Steuerung des Prozesses (Erfassung der Eingabe / Ausgabe usw.). Dies wird bevorzugt.
Brian
6
@PierreBdr: Es gibt einen Fall, in dem Rawstrings nicht funktionieren: Sie benötigen einen abschließenden Schrägstrich. zB r'c: \ foo \ bar \ '. Eigentlich ist es wahrscheinlich besser, stattdessen Schrägstriche zu verwenden. Diese werden in der gesamten Windows-API akzeptiert (allerdings nicht immer von einigen Shell-Befehlen (z. B. Kopieren))
Brian,
1
Für Python> = 3.5 subprocess.callsollte durch subprocess.run docs.python.org/3/library/subprocess.html#older-high-level-api
gbonetti
67

Hier ist eine andere Art, es zu tun.

Wenn Sie Windows verwenden, können Sie wie folgt im Explorer doppelklicken oder den Dateinamen als Argument für den DOS-Befehl "start" angeben: Die Datei wird mit jeder Anwendung (falls vorhanden) geöffnet, der ihre Erweiterung zugeordnet ist .

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

Beispiel:

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

Dadurch wird textfile.txt mit Notepad geöffnet, wenn Notepad mit TXT-Dateien verknüpft ist.

user16738
quelle
1
Gibt es eine äquivalente Funktion für * nix-Systeme?
Romeno
@Romeno: Sie könnten versuchen: webbrowser.open("textfile.txt")Es sollte einen Texteditor öffnen. Siehe auch "Starten Sie das zweite Programm ganz alleine, als hätte ich nur darauf doppelklickt".
JFS
Auf meinem Setup muss textfile.txt in Anführungszeichen stehen, zB:os.startfile('path\to\textfile.txt')
thdoan
34

Die äußersten Anführungszeichen werden von Python selbst verwendet, und die Windows-Shell sieht sie nicht. Wie oben erwähnt, versteht Windows nur doppelte Anführungszeichen. Python konvertiert unter Windows Schrägstriche in Schrägstriche, sodass Sie sie verwenden können

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

Das 'wird von Python verwendet, das dann "C: //Temp/abc/Notepad.exe" (als Windows-Pfad, keine doppelten Backslashes erforderlich) an CMD.EXE übergibt

Daniel Serodio
quelle
1
Dies scheint das Beste in einem Szenario zu sein, os.system('curl URL > file')in dem ich die Aktualisierung der Fortschrittsanzeige von cURL für wirklich große Dateien sehen möchte.
Zach Young
Wenn der erste Buchstabe nach einem Backslash besondere Bedeutung hat (dh \t, \nusw.) dann , dass bestimmte Backslash muss verdoppelt werden. Ein Windows-Pfad zu sein hat nichts damit zu tun.
Ethan Furman
1
Beachten Sie, dass bei Verwendung os.system()unter Windows das Cmd-Fenster geöffnet bleibt und geöffnet bleibt, bis Sie den gestarteten Prozess schließen. IMHO ist es besser zu verwenden os.startfile().
30.
1
Vergiss nichtimport os
Besi
funktioniert bei mir nicht stackoverflow.com/questions/56241616/…
Gulzar
19

Zumindest in Windows 7 und Python 3.1 os.systemmöchte Windows, dass die Befehlszeile in doppelte Anführungszeichen gesetzt wird, wenn der Pfad zum Befehl Leerzeichen enthält. Zum Beispiel:

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

Ein reales Beispiel, das mich verblüffte, war das Klonen eines Laufwerks in VirtualBox. Die subprocess.callobige Lösung funktionierte aufgrund eines Problems mit Zugriffsrechten nicht, aber als ich den Befehl doppelt zitierte, os.systemwurde ich glücklich:

  TheCommand = '\"\"C:\\Program Files\\Sun\\VirtualBox\\VBoxManage.exe\" ' \
                 + ' clonehd \"' + OrigFile + '\" \"' + NewFile + '\"\"'
  os.system(TheCommand)
Paul Hoffman
quelle
Das war's! Ich würde mich dafür entscheiden subprocess, aber manchmal os.systemund os.popen(...).read()sind einfach schneller zu tippen. Übrigens müssen Sie sich doppelten Anführungszeichen in einfachen Anführungszeichen nicht entziehen, das heißt '""C:\\Temp\\a b c\\Notepad.exe""'.
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
rahul
quelle
und es scheint, dass bei dieser Methode kein Anführungszeichen erforderlich ist, z. B. win32api.WinExec ('pythonw.exe d: \ web2py \ web2py.py -K welcome') startet den web2py-Scheduler im Hintergrund.
Tim Richardson
@rahul und außer Argumenten für die ausführbare Datei? Wenn Sie also möchten, dass Notepad eine Datei öffnet, oder ist das separat?
Sayth
3

Ich vermute, es ist das gleiche Problem wie bei der Verwendung von Verknüpfungen in Windows ... Versuchen Sie Folgendes:

import os;
os.system("\"C:\\Temp\\a b c\\Notepad.exe\" C:\\test.txt");
Matthew Scharley
quelle
Entschuldigung, das funktioniert auch nicht, bearbeitete Frage, um dies widerzuspiegeln.
Lasse V. Karlsen
Ich denke, Windows verwendet nur "und nicht" zum Zitieren. Dies wird wahrscheinlich funktionieren, wenn Sie dies ändern. Sie werden jedoch immer noch auf Probleme
Brian
Ich dachte, es hat beides gekostet, aber Sie haben wahrscheinlich Recht. Ich weiß, dass es (zumindest in der Shell) mit doppelten Anführungszeichen funktioniert.
Matthew Scharley
+1 Dies ist die beste, Windows XP, 2007 Home Edition hat gut funktioniert
0

Angenommen, wir möchten Ihren Django-Webserver (unter Linux) so ausführen, dass zwischen Ihrem Pfad (path = '/home/<you>/<first-path-section> <second-path-section>') Platz ist. Gehen Sie wie folgt vor:

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

[ Anmerkung ]:

  • Vergessen Sie nicht, auf die Berechtigung zuzugreifen: chmod 755 -R <'yor path'>
  • manage.py ist exceutable: chmod +x manage.py
Benyamin Jafari
quelle
0

Verwenden Sie für Python 3.7 subprocess.call . Verwenden Sie eine Rohzeichenfolge, um die Windows-Pfade zu vereinfachen:

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

Keine Notwendigkeit für Unterprozess, Es kann einfach durch erreicht werden

GitPath = "C: \ Programme \ Git \ git-bash.exe" # Pfad der Anwendungsdatei in mycase seine GITBASH os.startfile (GitPath)

Rajat Prakash
quelle