Schrift
[thread]5315[/thread]

Fortschrittsanzeige und Prozessabbruch: GUI mit pipe und fork

Leser: 2


<< >> 5 Einträge, 1 Seite
rudolf
 2007-05-21 13:06
#46339 #46339
User since
2007-05-21
3 Artikel
BenutzerIn
[default_avatar]
Hallo zusammen,

ich versuche mich gerade mit einer GUI für das Kommandozeilenprogramm aria2c.

Folgende Funktion möchte ich einbauen:
nach Start von aria2c soll das GUI aktiv bleiben und eine Fortschrittsanzeige sowie einen Cancel-Button beinhalten.

Ich gehe so vor (unter Linux):
(nur schematisch, bitte keine Syntaxfehler suchen)

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
use IO::Handle; 

if ($pid = open(CHILD, "-|")) {

   {erzeuge ein toplevel mit ProgressBar und Cancel-Button}

   repeat (500, {toplevel->update} );

   while <CHILD> {  
   {lese die Ausgabe von aria2c und zeige den Fortschritt an}
  }
   
   close(CHILD);

} else {    
   STDOUT->autoflush(1);
   exec  ( "aria2c", @options );    
   CORE::exit();
}



Beim Drücken des Cancel-Buttons soll "Kill 9" an den Kindprozess gesandt werden.

Mir gefällt nicht so gut, dass ich mit repeat und update das GUI aktiv halten muss, außerdem taucht der Cancel-Button zwar auf aber er reagiert nicht. Ich habe gelesen dass dies auch mit Tk::fileevent geht. Wie kriege ich dann einen sauberen Abschluss des Kindprozesses hin. Möglicherweise mit waitVariable? Wäre dies der bessere Weg?

Ein weiteres Problem ist der Output von aria2c. Der Fortschritt wird zwar mit %Zahlen angezeigt, aber immer in der gleichen Zeile (ohne Newline).
Dadurch liest mein Parentprozess nur die letzte Angabe mit 99 oder 100%, trotz autoflush.
Damit ist natürlich eine Fortschrittsanzeige nicht möglich. Wie kriege ich es hin, dass auch die Zwischenergebnisse verarbeitet werden?

Auch mit der STDERR-Ausgabe komme ich noch nicht klar. Momentan fällt die ganz unter den Tisch. Gibt es einen anderen Weg als diese Ausgabe in eine Datei zu schreiben und anschließend zu lesen? Eigentlich wollte ich die Shell ja ganz aus dem Spiel lassen.

Vielen Dank
Rudolf
murphy
 2007-05-21 15:39
#46340 #46340
User since
2004-07-19
1776 Artikel
HausmeisterIn
[Homepage]
user image
[quote=rudolf,21.05.2007, 11:06][...]
Code: (dl )
1
2
3
4
5
} else {    
STDOUT->autoflush(1);
exec ( "aria2c", @options );
CORE::exit();
}

[/quote]
Dieser Teil des Codes ergibt wenig Sinn. Autoflush auf STDOUT zu aktivieren hat für den Aufruf von CORE::exit keinerlei Effekt. Und falls der Aufruf von exec erfolgreich ist, hat es natürlich erst recht keinen Effekt, denn in dem Falle sind der gesamte Perlinterpreter und das laufende Skript aus dem Speicher des aktuellen Prozesses verschwunden und wurden durch das auszuführende Programm ersetzt.


[quote=rudolf,21.05.2007, 11:06][...]
Mir gefällt nicht so gut, dass ich mit repeat und update das GUI aktiv halten muss, außerdem taucht der Cancel-Button zwar auf aber er reagiert nicht. Ich habe gelesen dass dies auch mit Tk::fileevent geht.
[/quote]
Von Tk habe ich leider keine Ahnung, aber ich denke mal, dass diese Fileevent-Funktionalität ein Wrapper um den Systemaufruf select oder poll sein muss. Da kannst Du dann bestimmt sowohl darauf reagieren, dass dein Kindprozess neue Daten geschrieben hat, als auch darauf, dass er neue Daten lesen will oder darauf dass er seine Ausgabe geschlossen hat, weil er sich beendet hat.


[quote=rudolf,21.05.2007, 11:06][...]
Ein weiteres Problem ist der Output von aria2c. Der Fortschritt wird zwar mit %Zahlen angezeigt, aber immer in der gleichen Zeile (ohne Newline).
Dadurch liest mein Parentprozess nur die letzte Angabe mit 99 oder 100%, trotz autoflush.
[/quote]
Wie oben bereits erwähnt, hat das Aktivieren von Autoflush keinen Effekt, da Du ein externes Programm ausführst, keinen Perlcode.

Stattdessen solltest Du vielleicht entweder eine Kommandozeilenoption von aria2c suchen, die die Ausgabe modifiziert, oder vor dem Einlesen der Ausgabe das Eingabedatensatztrennzeichen modifizieren (local $/ = "\r" könnte hier helfen).


[quote=rudolf,21.05.2007, 11:06][...]
Auch mit der STDERR-Ausgabe komme ich noch nicht klar. Momentan fällt die ganz unter den Tisch. Gibt es einen anderen Weg als diese Ausgabe in eine Datei zu schreiben und anschließend zu lesen?[...]
[/quote]
Um nicht nur STDOUT oder STDIN bei einem Kindprozess umzuleiten gibt es die Standardmodule IPC::Open2 und IPC::Open3.


(edit: Tippfehler korrigiert)\n\n

<!--EDIT|murphy|1179747789-->
When C++ is your hammer, every problem looks like your thumb.
rudolf
 2007-05-22 02:01
#46341 #46341
User since
2007-05-21
3 Artikel
BenutzerIn
[default_avatar]
[quote=murphy,21.05.2007, 13:39]
Dieser Teil des Codes ergibt wenig Sinn. Autoflush auf STDOUT zu aktivieren hat für den Aufruf von CORE::exit keinerlei Effekt. Und falls der Aufruf von exec erfolgreich ist, hat es natürlich erst recht keinen Effekt, denn in dem Falle sind der gesamte Perlinterpreter und das laufende Skript aus dem Speicher des aktuellen Prozesses verschwunden und wurden durch das auszuführende Programm ersetzt.[/quote]
Da hast du wohl recht. Ich habe den Code aus verschiedenen Quellen zusammengetragen. Das CORE::exit wurde glaube ich empfohlen um die Prozesstabelle sauber zu halten, aber wahrscheinlich nicht zusammen mit exec(). Schaden dürften die Befehle aber wohl nicht.

[quote=murphy,21.05.2007, 13:39]Stattdessen solltest Du vielleicht entweder eine Kommandozeilenoption von aria2c suchen, die die Ausgabe modifiziert, oder vor dem Einlesen der Ausgabe das Eingabedatensatztrennzeichen modifizieren (local $/ = "\r" könnte hier helfen).[/quote]
Eine Kommandozeilenoption gibt es (noch) nicht.
Mit der local-Anweisung funktioniert es wunderbar. Vielen Dank für den Hinweis.

[quote=murphy,21.05.2007, 13:39]Um nicht nur STDOUT oder STDIN bei einem Kindprozess umzuleiten gibt es die Standardmodule IPC::Open2 und IPC::Open3.[/quote]
Das muss ich mir mal näher anschauen.

Danke.
rudolf
 2007-05-22 10:50
#46342 #46342
User since
2007-05-21
3 Artikel
BenutzerIn
[default_avatar]
Zum Problem
Code: (dl )
$mw->repeat(100,sub{$mw->update()});

habe ich im Forum folgende Aussage gefunden:
Quote
so wie's dasteht (update in kombination mit repeat), bringts in der regel nicht wirklich was...
$mw->repeat wird nur ausgefuehrt, wenn die Mainloop gerade mal wieder ausgefuehrt wird. wenn du also eine laengere funktion oder so hast, dann wird waehrenddessen das Tk::repeat nicht ausgefuehrt, weil Tk nur auf einem Thread/Prozess laeuft. und das update wird ja eh bei jedem durchlauf von mainloop ausgefuehrt.
$mw->update bringt nur was, wenn du eine laenger laufende funktion hast; da ist es dann oft schon sinnvoll, das von zeit zu zeit ausfuehren...

Aber wie bekomme ich es dann hin, dass das GUI während der Ausführung von aria2c aktiv bleibt?
ptk
 2007-05-23 22:35
#46343 #46343
User since
2003-11-28
3645 Artikel
ModeratorIn
[default_avatar]
Such mal nach dem Stichwort Tk::fileevent.
<< >> 5 Einträge, 1 Seite



View all threads created 2007-05-21 13:06.