Python 3.4 - Fehlerkanal mittels subprocess.check_output auslesen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Grendel
User
Beiträge: 50
Registriert: Samstag 19. Dezember 2015, 16:06

Hallo,

ich arbeite an einem GUI-Wrapper für diverse Kommandozeilen-Tools und bin auf eine Schwierigkeit gestoßen, wenn es darum geht, stderr auszulesen.

Zunächst versuchte ich, den Standardfehlerkanal auf stdout umzuleiten und eventuell auftretende Fehler mittels try...except abzufangen. Das funktioniert aber nicht ganz, wie erhofft:

Code: Alles auswählen

try:
	cmd_output = subprocess.check_output(["my_command", my_args], stderr=subprocess.STDOUT)

except subprocess.CalledProcessError as subp_err:
	print(cmd_output)
Der Code ist nur beispielhaft, jedenfalls läuft er im Fehlerfalle in einen "referenced before assignment"-Error, da cmd_output offensichtlich nur lokal für den try-Block gültig ist. Lese ich "subp_err" aus, dann erhalte ich lediglich die von Python generierte Fehlermeldung mit Exit-Code 1. Das Kommandozeilentool schreibt im Falle eines Fehlers aber etwas nach stderr, nur wie komme ich daran?

Gruß,
Andreas
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Grendel: cmd_output ist nicht nur lokal im try-Block gültig, sondern erst, wenn die Anweisung auch ausgeführt wurde. Wird sie aber nicht, weil in check_output eine Exception auftritt, und damit vor der Zuweisung in den except-Block gesprungen wird. Du leitest zwar stderr auf stdout, stdout wird aber nicht in eine subprocess.PIPE umgeleitet, so dass die Ausgabe auch nicht in cmd_output, bzw. im Fehlerfall subp_err.output landet.
Grendel
User
Beiträge: 50
Registriert: Samstag 19. Dezember 2015, 16:06

@Sirius
Danke für die Erläuterung. Jetzt weiß ich, warum es _nicht_ funktioniert. Aber wie bekomme ich das ans Laufen?
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Grendel: war das nicht klar? Eingerückt wird immer mit 4 Leerzeichen pro Ebene, nicht 3. subp_err ist eine kryptische Abkürzung, die doch gar nicht nötig ist:

Code: Alles auswählen

try:
    cmd_output = subprocess.check_output(
        ["my_command", my_args],
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as processerror:
    print(processerror.output)
Grendel
User
Beiträge: 50
Registriert: Samstag 19. Dezember 2015, 16:06

Ja, so habe ich das probiert. Provoziere ich dann aber einen Fehler in dem so gestarteten Prozess, der dann eine Fehlermeldung nach stderr schreibt, dann erhalte ich diese Fehlermeldung:

ValueError: stdout argument not allowed, it will be overridden.

Edit: ein Blick in "subprocess.py" ergibt dies:

Code: Alles auswählen

    if 'stdout' in kwargs:
        raise ValueError('stdout argument not allowed, it will be overridden.')
Edit2: okay, ich lasse den Teil mit "stdout" einfach weg, dann scheint es zu funktionieren.
Antworten