6121 Stimmen

Wie kann ich ein Programm ausführen oder einen Systembefehl aufrufen?

Wie rufe ich einen externen Befehl in Python auf, als hätte ich ihn in einer Shell oder Eingabeaufforderung eingegeben?

0 Stimmen

Ich verstehe das nicht, was ist falsch an import os; os.system('pip list | grep anatome') ? Zumindest kann man damit Piping machen, wie mein Beispiel zeigt. Es ist nicht klar, wie man das mit import subprocess; subprocess.run(["ls", "-l"]) .

55voto

Ben Hoffstein Punkte 99969

Verwenden Sie Unterprozess .

...oder für einen sehr einfachen Befehl:

import os
os.system('cat testfile')

48voto

fameman Punkte 2587

Ab dem Python 3.7.0 veröffentlicht am 27. Juni 2018 ( https://docs.python.org/3/whatsnew/3.7.html ) können Sie Ihr gewünschtes Ergebnis auf die wirkungsvollste und gleichzeitig einfachste Weise erreichen. Diese Antwort soll Ihnen einen kurzen Überblick über die verschiedenen Möglichkeiten geben. Ausführlichere Antworten finden Sie in den anderen Antworten.


TL;DR im Jahr 2021

Der große Vorteil von os.system(...) war seine Einfachheit. subprocess ist besser und immer noch einfach zu bedienen, insbesondere ab Python 3.5 .

import subprocess
subprocess.run("ls -a", shell=True)

Anmerkung: Dies ist die genaue Antwort auf Ihre Frage - ein Befehl wird ausgeführt

wie in einer Muschel


Bevorzugter Weg

Wenn möglich, entfernen Sie den Shell-Overhead und führen Sie den Befehl direkt aus (erfordert eine Liste).

import subprocess
subprocess.run(["help"])
subprocess.run(["ls", "-a"])

Programmargumente in einer Liste übergeben. Nicht einbeziehen \" -Escaping für Argumente, die Leerzeichen enthalten.


Erweiterte Anwendungsfälle

Prüfen der Ausgabe

Der folgende Code spricht für sich selbst:

import subprocess
result = subprocess.run(["ls", "-a"], capture_output=True, text=True)
if "stackoverflow-logo.png" in result.stdout:
    print("You're a fan!")
else:
    print("You're not a fan?")

result.stdout sind alle normalen Programmausgaben Ausschluss von Fehlern . Lesen Sie result.stderr um sie zu bekommen.

capture_output=True - schaltet die Erfassung ein. Andernfalls result.stderr y result.stdout wäre None . Erhältlich bei Python 3.7 .

text=True - ein praktisches Argument, das in Python 3.7 das die empfangenen Binärdaten in Python-Strings umwandelt, mit denen man leicht arbeiten kann.

Überprüfung des Rückgabecodes

Do

if result.returncode == 127: print("The program failed for some weird reason")
elif result.returncode == 0: print("The program succeeded")
else: print("The program failed unexpectedly")

Wenn Sie nur prüfen wollen, ob das Programm erfolgreich war (Returncode == 0) und andernfalls eine Exception auslösen wollen, gibt es eine bequemere Funktion:

result.check_returncode()

Da es sich aber um Python handelt, gibt es ein noch bequemeres Argument check die das Gleiche automatisch für Sie tut:

result = subprocess.run(..., check=True)

stderr sollte innerhalb von stdout liegen

Vielleicht möchten Sie alle Programmausgaben in stdout haben, auch Fehler. Um dies zu erreichen, führen Sie

result = subprocess.run(..., stderr=subprocess.STDOUT)

result.stderr wird dann None y result.stdout wird alles enthalten.

Verwendung von shell=False mit einer Argumentationskette

shell=False erwartet eine Liste der Argumente. Sie können eine Argumentationskette jedoch auch selbst mit shlex aufteilen.

import subprocess
import shlex
subprocess.run(shlex.split("ls -a"))

Das war's.

Allgemeine Probleme

Die Chancen stehen gut, dass Sie gerade mit Python angefangen haben, wenn Sie auf diese Frage stoßen. Schauen wir uns einige häufige Probleme an.

FileNotFoundError: [Errno 2] Keine solche Datei oder Verzeichnis: 'ls -a': 'ls -a'

Sie führen einen Unterprozess ohne shell=True . Entweder Sie verwenden eine Liste ( ["ls", "-a"] ) oder setzen shell=True .

TypFehler: [...] NoneType [...]

_Stellen Sie sicher, dass Sie die capture_output=True ._

TypeError: ein bytesartiges Objekt ist erforderlich, nicht [...]

Sie erhalten immer Byte-Ergebnisse aus Ihrem Programm. Wenn Sie damit wie mit einer normalen Zeichenkette arbeiten wollen, setzen Sie text=True .

subprocess.CalledProcessError: Der Befehl '[...]' gab einen Exit-Status ungleich Null zurück 1.

Ihr Befehl wurde nicht erfolgreich ausgeführt. Sie könnten die Returncode-Prüfung deaktivieren oder die Gültigkeit Ihres aktuellen Programms überprüfen.

TypFehler: init () hat ein unerwartetes Schlüsselwort-Argument erhalten [...]

Sie verwenden wahrscheinlich eine Python-Version, die älter als 3.7.0 ist; aktualisieren Sie sie auf die neueste verfügbare Version. Andernfalls gibt es andere Antworten in diesem Stack Overflow-Beitrag, die Ihnen ältere alternative Lösungen zeigen.

1 Stimmen

"Der große Vorteil von os.system(...) war seine Einfachheit. subprocess ist besser" - wie ist subprocess besser? Ich verwende gerne os.system und bin mir nicht sicher, wie der Wechsel zu subprocess und die Erinnerung an zusätzliche shell=True kommt mir zugute. Was ist in einem Teilprozess besser?

1 Stimmen

Sie haben Recht, dass os.system(...) ist eine vernünftige Wahl für die Ausführung von Befehlen im Sinne einer einfachen "blinden" Ausführung. Allerdings sind die Anwendungsfälle ziemlich begrenzt - sobald man die Ausgabe erfassen will, muss man eine ganz andere Bibliothek verwenden und dann fängt man an, beides zu haben - subprocess und os für ähnliche Anwendungsfälle in Ihrem Code. Ich ziehe es vor, den Code sauber zu halten und nur eine von beiden zu verwenden. Zweitens, und ich hätte diesen Abschnitt an den Anfang gestellt, aber das TL;DR muss die Frage beantworten genau sollten Sie no verwenden. shell=True sondern das, was ich in der Preferred Way Abschnitt.

1 Stimmen

Das Problem mit os.system(...) y shell=True ist, dass Sie einen neuen Shell-Prozess erzeugen, nur um Ihren Befehl auszuführen. Das bedeutet, dass Sie das Escaping manuell durchführen müssen, was nicht so einfach ist, wie Sie vielleicht denken - vor allem, wenn Sie sowohl POSIX als auch Windows anvisieren. Für Benutzereingaben ist das ein No-Go (stellen Sie sich vor, der Benutzer gibt etwas mit " Anführungszeichen - man müsste ihnen auch entgehen). Außerdem könnte der Shell-Prozess selbst Code laden, den Sie nicht brauchen - das verzögert nicht nur das Programm, sondern könnte auch zu unerwarteten Nebeneffekten führen und mit einem falschen Rückgabewert enden.

43voto

Martin W Punkte 1329

os.system ist OK, aber irgendwie veraltet. Außerdem ist es nicht sehr sicher. Versuchen Sie stattdessen subprocess . subprocess ruft sh nicht direkt auf und ist daher sicherer als os.system .

Mehr Informationen erhalten aquí .

3 Stimmen

Ich stimme zwar der allgemeinen Empfehlung zu, subprocess beseitigt nicht alle Sicherheitsprobleme und hat selbst einige lästige Eigenheiten.

40voto

stuckintheshuck Punkte 2391

Außerdem gibt es Plumbum

>>> from plumbum import local
>>> ls = local["ls"]
>>> ls
LocalCommand(<LocalPath /bin/ls>)
>>> ls()
u'build.py\ndist\ndocs\nLICENSE\nplumbum\nREADME.rst\nsetup.py\ntests\ntodo.txt\n'
>>> notepad = local["c:\\windows\\notepad.exe"]
>>> notepad()                                   # Notepad window pops up
u''                                             # Notepad window is closed by user, command returns

0 Stimmen

Eine Erklärung wäre angebracht.

33voto

Samadi Salahedine Punkte 517

Es kann so einfach sein:

import os
cmd = "your command"
os.system(cmd)

2 Stimmen

Dabei wird nicht auf die Nachteile hingewiesen, die viel ausführlicher in PEP-324 . Die Dokumentation für os.system empfiehlt ausdrücklich, sie zu vermeiden zugunsten von subprocess .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X