stdout und stderr mit PIPE in Konflikt zueinander?

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.
ivka_sto
User
Beiträge: 63
Registriert: Dienstag 11. Dezember 2007, 23:13

Hallo zusammen,

Ist es möglich, daß sich bei subprocess stdout und stderr gegenseitig blockieren? Oder (wenn auf PIPE umgeleitet) sich nicht einigen können, wer schreiben darf?

Ich knobel schon den ganzen Nachmittag rum, warum das geht:

Code: Alles auswählen

ini = subprocess.Popen('BeispielBefehl', shell = True, stderr = subprocess.PIPE)
und das führt mein Programm in einer bösen Endlosschleife (oder es sieht zumindest so aus, im Shell bleibt alles stehen, und läßt sich nicht mal manuell killen):

Code: Alles auswählen

ini = subprocess.Popen('BeispielBefehl', shell = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)

Wobei - ein anderer Befehl läuft auch mit dem zweiten Aufruf hervorragend .. Also, denk ich, daß es nur daran liegen kann, daß der Output des Befehls sowieso im Shell angezeigt wird, und eventuell in Konflikt mit stderr steht.

Ich vermute, ich habe einen Denkfehler irgendwo, oder übersehe etwas. Fällt jemandem mehr?


Viele Grüße,
ivka_sto
lunar

Vor allem solltest du mal auf "shell=True" verzichten.
ivka_sto
User
Beiträge: 63
Registriert: Dienstag 11. Dezember 2007, 23:13

Davon abgesehen :)

Nee, Sache ist, ich brauche den Shell, um die Interaktivität zu ermöglichen.
Noch was, der Output des Befehls wird eh im Shell ausgegeben - macht's dann überhaupt Sinn zu sagen 'stdout = subprocess.PIPE'?
BlackJack

Wieso brauchst Du die Shell für "interaktivität"?

Wenn ich mal raten müsste gibt das gestartete Programm nichts oder nur sehr wenig auf seinem 'stderr' aus, aber einiges auf seinem 'stdout' und Du liest das dann nicht aus, wodurch das Programm natürlich blockiert, weil es seine Ausgaben nicht mehr los wird.
ivka_sto
User
Beiträge: 63
Registriert: Dienstag 11. Dezember 2007, 23:13

Weil das Programm Berechnungen steuern soll, und es werden ab und an Koeffizienten u. ä. abgefragt.

Ich hab gerade festgestellt, daß das Problem nur auf stdout = subprocess.PIPE liegt, das Programm blockiert auch ohne stderr. Doch ich brauche später stdout.read, und kann es deshalb nicht auslassen .. Hat jemand ne Idee?
BlackJack

Das erklärt immer noch nicht wozu Du die Shell brauchst. Die Abfragen macht ja das gestartete Programm und nicht die Shell.

Nicht nur später `stdout` lesen, sondern sofort, denn das die Daten dort nicht abgenommen werden, ist ja der Grund warum es blockiert.

Wenn Du mit dem Programm wechselseitig kommunizieren willst, wirst Du aber wohl Probleme mit den Puffern zwischen den beiden Programmen bekommen. Dafür sollte man das `pexpect`-Modul verwenden.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

ivka_sto hat geschrieben:Noch was, der Output des Befehls wird eh im Shell ausgegeben - macht's dann überhaupt Sinn zu sagen 'stdout = subprocess.PIPE'?
Wenn du die Ausgaben Daten nicht in Python brauchst, dann man es keinen Sinn eine PIPE zu öffnen.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
ivka_sto
User
Beiträge: 63
Registriert: Dienstag 11. Dezember 2007, 23:13

@jens: Das hab ich anders gemeint, ich will die Ausgabedaten lesen können.

@BlackJack: Ich führe das Programm unter Shell aus. Sprich, ich starte extra keine grafische Oberfläche, sondern es läuft alles vereinfacht über die Shell.

Kann ich pexpect irgendwie umgehen? Mit Buffermaximierung, oder sonst irgendwas? Ich habe hier keine root-Rechte, und ich möchte meinen Code nicht an einem konkreten Rechner binden. Wenn ich pexpect verwende, dann muß ich es auch überall installieren, wo ich das Programm laufen lassen will.

Danke schonmal für die Antworten.
VG, ivka_sto
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

ivka_sto hat geschrieben:@BlackJack: Ich führe das Programm unter Shell aus. Sprich, ich starte extra keine grafische Oberfläche, sondern es läuft alles vereinfacht über die Shell.
Was du machst ist Shell -> Python-Programm -> Shell -> aufzurufendes Programm. Die zweite Shell ist vollständig überflüssig.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

@ivka_sto: Nein Du kannst `pexpect` nicht umgehen. Du hast einfach keinen Einfluss auf die Pufferung in anderen Prozessen.
ivka_sto
User
Beiträge: 63
Registriert: Dienstag 11. Dezember 2007, 23:13

@Leonidas: Wenn mein Auto Motorschaden hat, und ich es gleich verschrotten lassen kann, kümmert es mich entsprechend weniger, daß vorne am linken Blinker ein kaum bemerkbarer Kratzer ist. Danke für den Hinweis, daß die Shell überflüßig ist, doch:

Mein Programm blockiert, wenn ich das stdout von dem subprocess in nem Pipe umleiten will, und zwar direkt in der subprocess.Popen-Zeile. Will nichts ausgeben, will nichts in nem File schreiben, reagiert einfach nicht mehr. Ich möchte sehr gern dieses Problem als Erstes beseitigen, dann werd ich auch um die Schönheitsfehler korrigieren und die Überflüßigkeiten beseitigen, wenn das Programm einmal läuft, versprochen.
Wenn mir einer helfen kann dahin zu kommen, werde ich sehr sehr dankbar sein. Wenn einer irgendeine Vermutung haben sollte, die in diesem Posting noch nicht besprochen worden ist, nur zu.

VG,
ivka_sto
BlackJack

Ich habe es doch eigentlich schon mal geschrieben: Das Programm schreibt in sein `stdout` solange bis der Puffer voll ist und blockiert dann solange, bis Du anfängst das auszulesen.

Stell Dir dass als eine Art Eimer mit einem Wasserhahn unten vor, wo der externe Prozess oben seine Ausgabe reinfüllt bis der Eimer voll ist, und dann solange warten muss mit dem nachfüllen, bis Du den Wasserhahn aufdrehst und wieder Platz schaffst.
ivka_sto
User
Beiträge: 63
Registriert: Dienstag 11. Dezember 2007, 23:13

Das kann sein, doch ich versuche schon in der nächsten Zeile auszulesen, und zu dieser nächsten Zeile kommt der Compiler gar nicht.
Ich weiß nicht, ob so viel Output schon in den 2ms nach dem Starten geschrieben wird, deswegen frag ich, ob jemandem nicht noch ein möglicher Grund fürs Blockieren einfällt.
BlackJack

Zeig doch noch einmal den Quelltext den Du da jetzt konkret hast.
ivka_sto
User
Beiträge: 63
Registriert: Dienstag 11. Dezember 2007, 23:13

Jepp, da is' er:

Code: Alles auswählen

def run_pro(self, jobname):
   '''ruft Pro als subprocess auf, gibt anhand des stderr-Streams die Version aus, und startet ein Count-Down, das blockiert wird, sobald es sichersteht, das Pro läuft.'''
   
   # call Pro
   cmd = 'pro2002 -j' + jobname

   pro = subprocess.Popen(cmd, shell = True, stdout = subprocess.PIPE)
   
   stdout_file = open('stdout.txt', 'w')
   stdout_file.write(pro.stdout.read())
   stdout_file.close()
Ich weiß, daß das Schreiben ins File zeilenweise erfolgen sollte, doch ich wollte nicht rumwühlen, solange der Rest nicht funktioniert, ein Fehler hätte mir auch gezeigt, daß der Compiler zumindest versucht hat zu schreiben.
BlackJack

Beendet sich denn 'pro2002' irgendwann? Wenn nein: `read()` wartet solange bis alle Ausgaben von dem externen Programm gelesen sind und das Programm sein `stdout` schliesst.
ivka_sto
User
Beiträge: 63
Registriert: Dienstag 11. Dezember 2007, 23:13

Oh .. gerade das wollte ich nicht hören .. Gibt es da eingebaute Möglichkeiten zur Laufzeit mit dem Programm zu interagieren außer pexpect? Genauer gesagt, den StdOut zu lesen?
BlackJack

Nö. Nicht das ich wüsste.
ivka_sto
User
Beiträge: 63
Registriert: Dienstag 11. Dezember 2007, 23:13

Uund - ich bin's wieder! :lol:

Bevor ich die Hälfte meines Codes in den Müll schmeiße, noch eine Frage an BlackJack: Lohnt es sich, daß ich mir das Thema 'Threads' anschaue? Ich denke, das Programm würde immer noch sein StdOut bis zum Beenden puffern, aber gibt es möglicherweise unter den Thread-Funktionen etwas, anhand dessen ich kontrollieren könnte, ob das Unterprogramm leise weiterarbeitet und nicht festgefahren ist? Mit Threads kenne ich mich gar nicht aus, und wollte fragen ob es überhaupt Sinn macht, bevor ich mir tonnenweise Doku- und Forumeinträge durchlese.

Vielen Dank für die Antworten bis jetzt, haben mir die Funktionsweise von subprocess noch mal etwas deutlicher gemacht.

Viele Grüße,
ivka_sto
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ich weiß nicht welches Programm du startes. Vielleicht ist es aber eins, welches eine Datei erzeugt. Dann könnte man in einem seperaten Thread die Dateigröße abfragen und wenn sie wächst, läuft das Programm noch...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten