So führen Sie einen Bash-Befehl in einem Python-Skript aus

Antworten:

15

@ Milnes Antwort funktioniert, subprocess.call()gibt Ihnen aber wenig Rückmeldung.

Ich bevorzuge die Verwendung, subprocess.check_output()damit Sie analysieren können, was auf stdout gedruckt wurde:

 import subprocess
 res = subprocess.check_output(["sudo", "apt", "update"])
 for line in res.splitlines():
     # process the output line by line

check_output Löst beim Beenden des aufgerufenen Befehls bei Null einen Fehler aus

Beachten Sie, dass dies nicht aufgerufen wird bashoder eine andere Shell, wenn Sie das shellSchlüsselwortargument für die Funktion nicht angeben (dasselbe gilt für subprocess.call()und sollten Sie nicht, wenn dies nicht erforderlich ist, da dies ein Sicherheitsrisiko darstellt), die direkt aufruft Befehl.

Wenn Sie feststellen, dass Sie viele (verschiedene) Befehlsaufrufe aus Python ausführen, sollten Sie sich Plumbum ansehen . Damit können Sie die (IMO) lesbarer machen:

from plumbum.cmd import sudo, apt, echo, cut

res = sudo[apt["update"]]()
chain = echo["hello"] | cut["-c", "2-"]
chain()
Anthon
quelle
Wird empfohlen ( os.popenoder os.system) zu verwenden, zB res = os.popen('sudo apt update').read():? @Anthon
alper
1
@alper Lesen Sie 0324 python.org/dev/peps/pep-0324 . Das erklärt die Gründe dafür, subprocessobwohl os.systemund os.popenbereits existierten. Solche PEPs sind nicht trivial, um akzeptiert zu werden. Einige Leute haben viel mehr darüber nachgedacht, als Sie oder ich es jemals tun werden. Und subprocesshat sich seit 2003 verbessert, die anderen sind nur noch da für die Abwärtskompatibilität. Haben Sie die os.systemHandbuchseite bereits aktualisiert? Das Unterprozessmodul bietet leistungsstärkere Funktionen, um neue Prozesse zu erstellen und deren Ergebnisse abzurufen. Die Verwendung dieses Moduls ist der Verwendung dieser Funktion vorzuziehen.
Anthon
1
@alper Ja du könntest. Wie ich bereits angedeutet habe, dass dies ein potenzielles Sicherheitsrisiko darstellt, weiß ich nicht, warum dies Ihrer Meinung nach empfohlen wird. Und sudowenn man sich auf etwas beruft, wird das nur noch schlimmer. Vielleicht ist die Verwendung von Python-Apt eine bessere Lösung (das habe ich selbst nicht untersucht).
Anthon
1
@alper in diesem Fall werfen Sie einen Blick auf Plumbum , es lohnt sich, sich damit vertraut zu machen .
Anthon
1
@alper Wenn Sie auf Python3 sind, müssen Sie das tun, auf Python2 nicht. Bitte benutze den Kommentar hier nicht als Chat-System. Wenn du eine Frage hast, poste sie als solche.
Anthon
8

Es ist möglich, dass Sie die Bash als Programm verwenden, mit dem Parameter -c, um die Befehle auszuführen:

Beispiel:

bashCommand = "sudo apt update"
output = subprocess.check_output(['bash','-c', bashCommand])
Rasierer
quelle
6

Das Subprozessmodul ist dazu ausgelegt:

import subprocess
subprocess.call(["sudo", "apt", "update"])

Wenn Sie möchten, dass das Skript beendet wird, wenn der Befehl fehlschlägt, sollten Sie in Betracht ziehen, check_call()den Rückkehrcode selbst zu analysieren , anstatt ihn zu verwenden:

subprocess.check_call(["sudo", "apt", "update"])
Milind Dumbare
quelle
Dies gab mir den folgenden Traceback: Traceback (most recent call last): File "/home/Dremor/test.py", line 3, in <module> subprocess.call('sudo', 'yum', 'update') File "/usr/lib64/python3.4/subprocess.py", line 537, in call with Popen(*popenargs, **kwargs) as p: File "/usr/lib64/python3.4/subprocess.py", line 767, in __init__ raise TypeError("bufsize must be an integer") TypeError: bufsize must be an integer (Ich verwende Yum, da ich Fedora als Hauptbetriebssystem verwende)
Dremor
3
Sie haben die eckigen Klammern vergessen
Milind Dumbare
1
Beachten Sie auch, dass subprocess.call()blockiert wird, während subprocess.Popen()nicht blockiert wird ..
heemayl
Was meinst du mit "Sperren"? @heemayl
alper
2

Sie können auch 'os.popen' verwenden.

Beispiel:

import os

command = os.popen('ls -al')
print(command.read())
print(command.close())

Ausgabe:

total 16
drwxr-xr-x 2 root root 4096 ago 13 21:53 .
drwxr-xr-x 4 root root 4096 ago 13 01:50 ..
-rw-r--r-- 1 root root 1278 ago 13 21:12 bot.py
-rw-r--r-- 1 root root   77 ago 13 21:53 test.py

None
ricardo130
quelle
0

Subprozessmodul verwenden

import subprocess
command = 'sudo apt update'
subprocess.check_call(command.split())
Fred
quelle
Warum
bekomme
subprocess.check_call (["sudo", "apt", "update"])
Aquagremlin
CalledProcessError Traceback (letzter Aufruf zuletzt) ​​<ipython-input-21-33ce645708e7> in <module> () ----> 1 subprocess.check_call (["sudo", "apt", "update"]) / usr / lib / python2.7 / subprocess.pyc in check_call (* popenargs, ** kwargs) 188 wenn cmd None ist: 189 cmd = popenargs [0] -> 190 raise CalledProcessError (retcode, cmd) 191 return 0 192 CalledProcessError: Command '[' sudo ',' apt ',' update ']' hat den Ausgangsstatus 1
aquagremlin
Dieser Fehler tritt nur auf, wenn ich ihn in einem Jupyter-Notizbuch
Aquagremlin
vielleicht
fange