Neuer Versuch: stderr abfangen !

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
Bluekobalt
User
Beiträge: 26
Registriert: Montag 20. Juli 2009, 11:08

Hallo leider ging gestern von meiner Seite aus ne Menge schief, deswegen möchte ich euch noch einmal bitten mir zu helfen:

Ich möchte den stderr abfangen und befinde mich in einem Windows System.

Code: Alles auswählen

 proc = subprocess.Popen(args, stdout=subprocess.PIPE,  stderr=subprocess.PIPE)
    proc.wait()
Wichtig ist,dass der childprozess beendet sein mus, bevor es weitergeht.
So wie der Code jetzt da steht, wartet proc.wait() zwar, aber ich muss den Child "per Hand abbrechen" was mir in meinem Fall nicht weiterhift.

Die Frage ist also wie muss ich wait() füttern, damit das Programm nach Beendigung des Childs weiterläuft ??
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Die Lösung ist abhängig davon, wie man den Child-Prozess beenden kann. Wenn das über eine Konsoleneingabe möglich ist (hier 'enDE'), wäre das hier eine Lösung:

Code: Alles auswählen

# File Test.py
import subprocess
proc = subprocess.Popen(['C:\\Programme\\Python26\\python.exe', 'return.py'],
                        stdin=subprocess.PIPE,
                        stdout=subprocess.PIPE,
                        stderr=subprocess.STDOUT)
print proc.communicate('Hallo\nenDE')

Code: Alles auswählen

# File return.py
import sys
while True:
    input_ = sys.stdin.readline()
    sys.stdout.write(input_)
    sys.stdout.flush()
    if 'enDE' in input_:
        break
Parent Test.py ruft hier also Child return.py auf, schreibt 'Hallo\nenDE' auf die Konsole. Durch 'enDE' wird return.py beendet. Schließlich werden stdout und stderr ausgegeben.
MfG
HWK
Bluekobalt
User
Beiträge: 26
Registriert: Montag 20. Juli 2009, 11:08

Vielen Dank für Deine Lösung, aber leider ist die Konsoleneingabe keine Lösung, weil es sich um ein automatisches Programm handeln soll.

Es ist wirklich zum verzweifeln!!

:cry:
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Bluekobalt hat geschrieben:...aber ich muss den Child "per Hand abbrechen"...
Wie machst Du das denn per Hand?
MfG
HWK
Bluekobalt
User
Beiträge: 26
Registriert: Montag 20. Juli 2009, 11:08

Na, das Programm über den Task Manager stoppen.
Allerdings bekomme ich dann auch nicht meine Ergebnisse.

Ich habe mir auch schon überlegt eine While Schleife zu bauen um nach den Ergebnissen zu fragen und dann abzubrechen. Dazu wäre dann dein Ansatz hilfreich.
Leider ist aber dieser workaround sehr umständlich, weil alle Klassen die meinen gekapselten Exe Wrapper aufrufen dann eine solche Behandlung benötigen.....
BlackJack

@Bluekobalt: Wenn das gestartete Programm ausgaben auf sein stdout und/oder stderr macht, dann wartest Du natürlich "ewig" auf das Ende. Denn das Programm wird sich erst beenden, wenn diese Ausgaben auch ausgelesen wurden.
lunar

Soll heißen, sobald ein "PIPE" im "Popen()"-Aufruf steht, musst dem fast zwangsläufig ein Aufruf von ".communicate()" folgen. Alternativ kann man auch stückchenweise direkt von ".stdout" und ".stderr" lesen, was aber komplizierter ist.

stdin muss man dafür nicht zwangsläufig umleiten.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Kannst Du denn genauere Angaben zu Deinem Child-Programm machen?
MfG
HWK
Bluekobalt
User
Beiträge: 26
Registriert: Montag 20. Juli 2009, 11:08

das ist ein RTF Parser, der mir RTF Dokumente in ein Druckdatenstrom konvertiert.

Sind die Dokument sehr klein, funzt alles tadelos.
Bei sehr großen Dokumenten, läuft das Skript einfach weiter, ohne auf die Antwort des Parsers zu warten.


@lunar

das hört sich interessant an, ich muss also ".communicate()" direkt in die nächste Zeile schreiben, ohne Parameter ?
'tschuldigung, wenn ich so doof frage, aber ich habe das schon ausprobiert und es hat nicht funktioniert, weil mein child wieder 'ewig' gehangen hat...
lunar

Ja, Du musst "in die nächste Zeile .communicate() schreiben". Wenn Du das schon erfolglos probiert hast, liegt Dein Fehler an anderer Stelle. Wo kann man nicht sagen, da Du den exakten Aufruf nicht gezeigt hast.
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Bluekobalt hat geschrieben:Sind die Dokument sehr klein, funzt alles tadelos.
Bei sehr großen Dokumenten, läuft das Skript einfach weiter, ohne auf die Antwort des Parsers zu warten.
Pipes haben eine begrenzte Größe. Wenn Popen.stdout oder Popen.stderr voll sind, kann das Programm nicht weiter machen und blockiert. Genau das steht doch auch als dicke fette rot hinterlegte Warnung bei Popen.wait() ...
Warning: This will deadlock if the child process generates enough output to a stdout or stderr pipe such that it blocks waiting for the OS pipe buffer to accept more data. Use communicate() to avoid that.
Du musst die Daten also aus den Pipes aus lesen, während das Programm noch läuft, damit es weiter arbeiten kann. Popen.communicate() nimmt dir diese Arbeit ab.
Bottle: Micro Web Framework + Development Blog
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Der Druckdatenstrom dürfte ja auch Sonderzeichen liefern, möglicherweise also auch End-Of-File (Ctrl-Z). Vielleicht liegt es daran?
MfG
HWK
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@Bluekobalt:
Kannst vllt. ein wenig mehr zur Funktionalität des Konverters sagen? Ob dieser sich zB beendet, wenn er mit einem Dokument fertig ist oder ob er mehrere Dokumente abarbeiten kann oder gar als System-Dienst läuft?

Falls er mehrere Dokumente behandelt, wäre hier interessant, wie er das Ende eines Dokumentes signalisiert usw.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Vielleicht sind diese beiden Threads noch hilfreich für Dich.
MfG
HWK
Antworten