Ich habe mich über die Funktionen des Unterprozesses - call, check_call, check_output - informiert und verstehe, wie die einzelnen Funktionen funktionieren und sich in ihrer Funktionalität voneinander unterscheiden. Ich verwende derzeit check_output, damit ich auf das stdout zugreifen kann, und habe "try block" verwendet, um die Ausnahme wie folgt abzufangen:
# "cmnd" is a string that contains the command along with it's arguments.
try:
cmnd_output = check_output(cmnd, stderr=STDOUT, shell=True, timeout=3, universal_newlines=True);
except CalledProcessError:
print("Status : FAIL")
print("Output: \n{}\n".format(cmnd_output))
Das Problem, auf das ich stoße, ist, wenn eine Ausnahme ausgelöst wird, "cmnd_output" nicht initialisiert wird und keinen Zugriff auf stderr hat und die folgende Fehlermeldung angezeigt wird:
print("Output: \n{}\n".format(cmnd_output))
UnboundLocalError: local variable 'cmnd_output' referenced before assignment
Ich denke, das liegt daran, dass die Ausnahme dazu führt, dass der "check_output" sofort ohne weitere Verarbeitung, auch bekannt als Zuweisung zu "cmnd_output", im try-Block abgebrochen wird. Bitte korrigieren Sie mich, wenn ich falsch liege.
Gibt es eine Möglichkeit, auf stderr zuzugreifen (es ist in Ordnung, wenn es an stout gesendet wird) und Zugriff auf den Exit-Code zu haben? Ich kann anhand des Exit-Codes manuell prüfen, ob bestanden / nicht bestanden wurde, ohne dass eine Ausnahme vorliegt.
Danke, Ahmed.
quelle
ret = subprocess.check_output(cmd , stderr=STDOUT,shell=True)
NameError: global name 'STDOUT' is not defined
stderr=STDOUT
, wenn Sie diesen Ansatz versuchentimeout
wird verwendet, weil der Code von OP es verwendet hat. Offensichtlich ist alles außercmnd
optional.Die akzeptierte Lösung deckt den Fall ab, in dem Sie in Ordnung mischen
stdout
undstderr
in Fällen, in denen der untergeordnete Prozess (aus welchem Grund auch immer) beschließt,stderr
IN ADDITIONstdout
für eine nicht fehlgeschlagene Ausgabe zu verwenden (dh eine unkritische Warnung auszugeben) Die gegebene Lösung ist möglicherweise nicht wünschenswert.Wenn Sie beispielsweise eine zusätzliche Verarbeitung für die Ausgabe durchführen, z. B. eine Konvertierung in JSON, und die Daten einmischen
stderr
, schlägt der Gesamtprozess fehl, da die Ausgabe aufgrund der hinzugefügtenstderr
Ausgabe kein reines JSON ist .Ich habe festgestellt, dass in diesem Fall Folgendes funktioniert:
cmd_args = ... what you want to execute ... pipes = subprocess.Popen(cmd_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) #If you are using python 2.x, you need to include shell=True in the above line std_out, std_err = pipes.communicate() if pipes.returncode != 0: # an error happened! err_msg = "%s. Code: %s" % (std_err.strip(), pipes.returncode) raise Exception(err_msg) elif len(std_err): # return code is 0 (no error), but we may want to # do something with the info on std_err # i.e. logger.warning(std_err) # do whatever you want with std_out # i.e. json.loads(std_out)
quelle
stderr=subprocess.PIPE
? Ich habe andere Posts gesehen, die es ohne die zusätzliche Pipe gemacht haben, und ich bin mir nicht sicher, warum..decode("utf-8")
After the Err's, da sie aus irgendeinem Grund in Bytes zurückgegeben werden.Beide vorgeschlagenen Lösungen mischen entweder stdout / stderr oder verwenden
Popen
eine nicht ganz so einfache Verwendung wiecheck_output
. Sie können jedoch dasselbe erreichen und stdout / stderr getrennt halten, während Sie verwenden,check_output
wenn Sie stderr einfach mit einer Pipe erfassen :import sys import subprocess try: subprocess.check_output(cmnd, stderr=subprocess.PIPE) except subprocess.CalledProcessError as e: print('exit code: {}'.format(e.returncode)) print('stdout: {}'.format(e.output.decode(sys.getfilesystemencoding()))) print('stderr: {}'.format(e.stderr.decode(sys.getfilesystemencoding())))
In diesem Beispiel ist es, da wir stderr erfasst haben, im
stderr
Attribut der Ausnahme verfügbar (ohne Erfassung mit der Pipe wäre dies nur der FallNone
).quelle
Note: Do not use stderr=PIPE with this function as that can deadlock based on the child process error volume. Use Popen with the communicate() method when you need a stderr pipe.
tee
Befehl tun wollten, ist dies in Python im Großen und Ganzen unmöglich, da Sie nicht viel mit Dateideskriptoren tanzen und die gesamte Arbeit über Systemaufrufe erledigen müssen. Diesubprocess
API ist vom Design her fehlerhaft.CalledProcessError.stderr
. Frühere Versionen nur habenreturncode
,cmd
undoutput
.Ich hatte eine ähnliche Anforderung und Folgendes funktionierte für mich:
try: with open ("vtcstderr.out", "w") as file: rawOutput = subprocess.check_output( command, stderr=file, shell=True ) except subprocess.CalledProcessError as error: # this is the stdout rawOutput = error.output with open ("vtcstderr.out", "r") as file: # this is the stderr errorLines = file.readlines()
quelle
Warum nicht die Variable cmnd_output vor der try-Anweisung initialisieren? Auf diese Weise funktioniert es so, wie Sie es erwarten. Die folgende Zeile würde funktionieren, fügen Sie sie einfach über der try-Anweisung hinzu:
cmnd_output = ''
quelle