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

stdout und stderr mit PIPE in Konflikt zueinander?

Beitragvon ivka_sto » Donnerstag 6. November 2008, 17:08

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

Beitragvon lunar » Donnerstag 6. November 2008, 17:19

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

Beitragvon ivka_sto » Donnerstag 6. November 2008, 17:27

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

Beitragvon BlackJack » Donnerstag 6. November 2008, 17:31

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

Beitragvon ivka_sto » Donnerstag 6. November 2008, 17:40

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

Beitragvon BlackJack » Donnerstag 6. November 2008, 18:00

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
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Freitag 7. November 2008, 08:33

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.

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
ivka_sto
User
Beiträge: 63
Registriert: Dienstag 11. Dezember 2007, 23:13

Beitragvon ivka_sto » Montag 10. November 2008, 12: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
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Montag 10. November 2008, 13:03

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 Modvoice
BlackJack

Beitragvon BlackJack » Montag 10. November 2008, 13:04

@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

Beitragvon ivka_sto » Montag 10. November 2008, 13:47

@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

Beitragvon BlackJack » Montag 10. November 2008, 14:13

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

Beitragvon ivka_sto » Montag 10. November 2008, 14:27

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

Beitragvon BlackJack » Montag 10. November 2008, 14:36

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

Beitragvon ivka_sto » Montag 10. November 2008, 14:55

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.

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder