Weisen Sie einer Variablen die Ausgabe von os.system zu und verhindern Sie, dass sie auf dem Bildschirm angezeigt wird

305

Ich möchte die Ausgabe eines Befehls, den ich verwende os.system, einer Variablen zuweisen und verhindern, dass sie auf dem Bildschirm ausgegeben wird. Im folgenden Code wird die Ausgabe jedoch an den Bildschirm gesendet und der Wert, für den gedruckt varwird, ist 0, was vermutlich bedeutet, ob der Befehl erfolgreich ausgeführt wurde oder nicht. Gibt es eine Möglichkeit, die Befehlsausgabe der Variablen zuzuweisen und zu verhindern, dass sie auf dem Bildschirm angezeigt wird?

var = os.system("cat /etc/services")
print var #Prints 0
John
quelle
2
mögliches Duplikat von Äquivalent von Backticks in Python
msw
4
Verwenden Sie nicht os.system(noch os.popengemäß der Antwort, die Sie akzeptiert haben): Verwenden Sie subprocess.Popen, es ist viel besser!
Alex Martelli
1
@AlexMartelli, man kann keine komplexen Befehle (zB piped) in subprocess.Popen () verwenden, aber mit os.system kann man
vak
2
@vak, natürlich kannst du Pfeifen & c w / verwenden subprocess.Popen- einfach hinzufügen shell=True!
Alex Martelli
@AlexMartelli shell=Trueist (generell) eine sehr schlechte Idee! Sie müssen sehr sicher sein, was Sie ausführen :)
Ignacio Fernández

Antworten:

444

Aus " Äquivalent von Bash Backticks in Python ", das ich vor langer Zeit gefragt habe, möchten Sie möglicherweise Folgendes verwenden popen:

os.popen('cat /etc/services').read()

Aus den Dokumenten für Python 3.6 ,

Dies wird mit subprocess.Popen implementiert. In der Dokumentation dieser Klasse finden Sie leistungsfähigere Möglichkeiten zum Verwalten und Kommunizieren mit Unterprozessen.


Hier ist der entsprechende Code für subprocess:

import subprocess

proc = subprocess.Popen(["cat", "/etc/services"], stdout=subprocess.PIPE, shell=True)
(out, err) = proc.communicate()
print "program output:", out
Chris Bunch
quelle
6
Beachten Sie, dass Walters subprocess.check_outputLösung näher an dem Pythonic-Einzeiler liegt, nach dem Sie anscheinend suchen, solange Sie sich nicht darum kümmern stderr.
chbrown
11
@ChrisBunch Warum ist Suprocess eine bessere Lösung als os.popen?
Martin Thoma
6
Sie sollten (fast) nie verwenden shell=True. Siehe docs.python.org/3/library/…
dylnmc
44
Ich stoße immer wieder darauf und jedes Mal, wenn ich mich frage - warum ist es besser, drei Zeilen komplizierten Codes zu haben, als eine Zeile offensichtlichen Codes?
Ant6n
3
Sie sollten nicht nur (fast) nie verwenden shell=True, sondern es ist auch in diesem Fall falsch. shell=Truemacht die Shell eher zum catouterrcat
untergeordneten
180

Vielleicht möchten Sie sich auch das subprocessModul ansehen , das die gesamte Familie der popenAufrufe vom Typ Python ersetzt .

import subprocess
output = subprocess.check_output("cat /etc/services", shell=True)

Der Vorteil ist, dass es eine Menge Flexibilität gibt, wie Sie Befehle aufrufen, wo die Standard-In / Out / Error-Streams verbunden sind usw.

Walter Mundt
quelle
2
Hinweis, check_outputwurde mit Python 2.7 docs.python.org/2.7/library/…
Phyatt
1
Hinzufügen stderr=subprocess.STDOUT, um auch Standardfehler zu erfassen
Dolan Antenucci
47

Das Befehlsmodul ist eine relativ gute Möglichkeit, dies zu tun:

import commands
status, output = commands.getstatusoutput("cat /etc/services")

Status ist 0, Ausgabe ist der Inhalt von / etc / services.

ianmclaury
quelle
43
Zitat aus der Dokumentation des Befehlsmoduls : "Veraltet seit Version 2.6: Das Befehlsmodul wurde in Python 3 entfernt. Verwenden Sie stattdessen das Unterprozessmodul." .
Cristian Ciupitu
4
Sicher, es ist veraltet, aber manchmal möchten Sie einfach etwas schnell und einfach in ein paar Codezeilen erledigen.
anon58192932
5
@advocate checkt den Befehl check_output des Unterprozesses aus. Es ist schnell, einfach und wird nicht so schnell abwerten!
Luke Stanley
29

Für Python 3.5+ wird empfohlen, die Ausführungsfunktion des Unterprozessmoduls zu verwenden . Dies gibt ein CompletedProcessObjekt zurück, von dem Sie leicht die Ausgabe sowie den Rückkehrcode erhalten können. Da Sie nur an der Ausgabe interessiert sind, können Sie einen solchen Utility-Wrapper schreiben.

from subprocess import PIPE, run

def out(command):
    result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True, shell=True)
    return result.stdout

my_output = out("echo hello world")
# Or
my_output = out(["echo", "hello world"])
Chiel ten Brinke
quelle
Vergessen Sie nicht die Option "capture_output = True" für run ()
Elysiumplain
24

Ich weiß, dass dies bereits beantwortet wurde, aber ich wollte eine potenziell besser aussehende Möglichkeit vorstellen, Popen über die Verwendung von from x import xund Funktionen aufzurufen :

from subprocess import PIPE, Popen


def cmdline(command):
    process = Popen(
        args=command,
        stdout=PIPE,
        shell=True
    )
    return process.communicate()[0]

print cmdline("cat /etc/services")
print cmdline('ls')
print cmdline('rpm -qa | grep "php"')
print cmdline('nslookup google.com')
Vasili Syrakis
quelle
1
3 Jahre später hat das bei mir funktioniert. Ich warf dies in eine separate Datei namens cmd.py, und dann schrieb from cmd import cmdlineund verwendete ich es in meiner Hauptdatei nach Bedarf.
Tarife KA
1
Ich habe das gleiche Problem mit os.system bekommen, das 0 zurückgibt, aber ich habe diese Methode ausprobiert und sie funktioniert großartig! Und als Bonus sieht es schön und ordentlich aus :) Danke!
Sophie Muspratt
4

Ich mache es mit der temporären Datei von os.system:

import tempfile,os
def readcmd(cmd):
    ftmp = tempfile.NamedTemporaryFile(suffix='.out', prefix='tmp', delete=False)
    fpath = ftmp.name
    if os.name=="nt":
        fpath = fpath.replace("/","\\") # forwin
    ftmp.close()
    os.system(cmd + " > " + fpath)
    data = ""
    with open(fpath, 'r') as file:
        data = file.read()
        file.close()
    os.remove(fpath)
    return data
Lexa-b
quelle
1

In Python 2.6 und 3 wird ausdrücklich empfohlen, die Verwendung von PIPE für stdout und stderr zu vermeiden.

Der richtige Weg ist

import subprocess

# must create a file object to store the output. Here we are getting
# the ssid we are connected to
outfile = open('/tmp/ssid', 'w');
status = subprocess.Popen(["iwgetid"], bufsize=0, stdout=outfile)
outfile.close()

# now operate on the file
Kearney Taaffe
quelle