Abrufen der Ausgabe von subprocess.call () [Duplikat]
-
22-09-2019 - |
Frage
Diese Frage bereits eine Antwort hier:
Wie kann ich die Ausgabe eines Prozessdurchlauf mit subprocess.call()
bekommen?
ein StringIO.StringIO
Objekt stdout
Passing gibt diesen Fehler:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 444, in call
return Popen(*popenargs, **kwargs).wait()
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 588, in __init__
errread, errwrite) = self._get_handles(stdin, stdout, stderr)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 945, in _get_handles
c2pwrite = stdout.fileno()
AttributeError: StringIO instance has no attribute 'fileno'
>>>
Lösung
Die Ausgabe von subprocess.call()
sollte nur auf Dateien umgeleitet werden.
Sie sollten subprocess.Popen()
stattdessen verwenden. Dann können Sie subprocess.PIPE
für die stderr, stdout passieren und / oder stdin Parameter und lesen aus den Rohren durch die communicate()
Methode:
from subprocess import Popen, PIPE
p = Popen(['program', 'arg1'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
output, err = p.communicate(b"input data that is passed to subprocess' stdin")
rc = p.returncode
Die Begründung ist, dass die Datei-ähnliche Objekt von subprocess.call()
verwendet wird, muss eine echte Dateideskriptors hat und somit die fileno()
Methode zu implementieren. Verwendung nur eine beliebige Datei-ähnliches Objekt wird nicht den Trick.
Siehe hier für weitere Informationen.
Andere Tipps
Wenn Sie Python-Version> = 2.7, können Sie subprocess.check_output , die genau im Grunde tut, was Sie wollen (es Standardausgabe als String zurückgibt).
Einfaches Beispiel (Linux-Version, siehe Anmerkung):
import subprocess
print subprocess.check_output(["ping", "-c", "1", "8.8.8.8"])
Beachten Sie, dass der Ping-Befehl Linux-Notation verwendet (-c
für count). Wenn Sie dies unter Windows versuchen, erinnern sie für gleiches Ergebnis zu -n
ändern.
Wie weiter unten Sie kommentiert eine ausführlichere Erklärung in dieser anderen Antwort finden.
ich die folgende Lösung. Es fängt den Exit-Code, die stdout und die stderr zu dem ausgeführten externen Befehl:
import shlex
from subprocess import Popen, PIPE
def get_exitcode_stdout_stderr(cmd):
"""
Execute the external command and get its exitcode, stdout and stderr.
"""
args = shlex.split(cmd)
proc = Popen(args, stdout=PIPE, stderr=PIPE)
out, err = proc.communicate()
exitcode = proc.returncode
#
return exitcode, out, err
cmd = "..." # arbitrary external command, e.g. "python mytest.py"
exitcode, out, err = get_exitcode_stdout_stderr(cmd)
Ich habe auch eine Blog-Post auf das hier .
Edit: wurde die Lösung auf eine neuere Version aktualisiert, die nicht auf Temperatur zu schreiben muss. Dateien.
Für Python 3.5 oder höher wird empfohlen, dass Sie die Lauffunktion aus der Verwendung Subprozess Modul . Dies gibt ein CompletedProcess
Objekt, von dem Sie bequem die Ausgabe sowie Rückkehrcode erhalten können.
from subprocess import PIPE, run
command = ['echo', 'hello']
result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True)
print(result.returncode, result.stdout, result.stderr)
Ich dachte nur vor kurzem, wie dies zu tun, und hier einige Beispiel-Code aus einem aktuellen Projekt von mir:
#Getting the random picture.
#First find all pictures:
import shlex, subprocess
cmd = 'find ../Pictures/ -regex ".*\(JPG\|NEF\|jpg\)" '
#cmd = raw_input("shell:")
args = shlex.split(cmd)
output,error = subprocess.Popen(args,stdout = subprocess.PIPE, stderr= subprocess.PIPE).communicate()
#Another way to get output
#output = subprocess.Popen(args,stdout = subprocess.PIPE).stdout
ber = raw_input("search complete, display results?")
print output
#... and on to the selection process ...
Sie haben nun die Ausgabe des Befehls in der Variablen „Ausgang“ gespeichert. „Stdout = subprocess.PIPE“ erzählt die Klasse ein Dateiobjekt namens ‚stdout‘ aus Popen zu erstellen. Die Kommunikation () -Methode, von dem, was ich sagen kann, verhält sich als eine bequeme Art und Weise ein Tupel der den Ausgang und die Fehler aus dem Prozess, den Sie ausgeführt haben zurückzukehren. Auch der Prozess wird ausgeführt, wenn die Instanziierung Popen.
In Ipython
Shell:
In [8]: import subprocess
In [9]: s=subprocess.check_output(["echo", "Hello World!"])
In [10]: s
Out[10]: 'Hello World!\n'
Basierend auf Sargue Antwort. Kredit Sargue.
Die folgenden Aufnahmen stdout und stderr des Prozesses in einer einzigen Variablen. Es ist Python 2 und 3 kompatibel:
from subprocess import check_output, CalledProcessError, STDOUT
command = ["ls", "-l"]
try:
output = check_output(command, stderr=STDOUT).decode()
success = True
except CalledProcessError as e:
output = e.output.decode()
success = False
Wenn Ihr Befehl ist eine Zeichenfolge, anstatt ein Array, Präfix dies mit:
import shlex
command = shlex.split(command)