Konsole umleiten in wxFenster

Plattformunabhängige GUIs mit wxWidgets.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

The Hit-Man hat geschrieben:so, hier die Ausgabe, wenn ich cdda2wav komplett ausgeführt habe ( nimmt defaultmäßig doch nur den ersten Track ) und siehe da, es kommt auch was ;) Allerdings erst, wenn sich das Programm beendet hat
Hallo Hit-Man!

Und jetzt die Möglichkeiten, die ich kennen.

1.) Du fütterst cdda2wav mit den einzelnen Tracks und bekommst erst dann eine Meldung zurück, wenn ein einzelner Track fertig ist. Ich glaube, aus dem Quellcode von jripper entnommen zu haben, dass die es genau so machen. Das ist wohl die einfachste Lösung.

2.) Du nimmst Linux, denn damit kannst du eine Konsolenanwendung vortäuschen und bekommst die Rückgabe sofort.

3.) Du schreibst die Autoren des Programmes ccda2wav an und fragst nach, ob sie eine Möglichkeit kennen, wie man die Rückgabe unter Windows sofort bekommt oder ob sie einen Kommandozeilenparameter zur Verfügung stellen können, mit dem das Programm nach jeder Ausgabe einen Flush durchführt.

Wie gesagt, das sind die Möglichkeiten, die ich kenne. Mal sehen, was die Anderen dazu zu sagen haben.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
The Hit-Man
User
Beiträge: 435
Registriert: Montag 20. Februar 2006, 18:11
Wohnort: Menden / Sauerland
Kontaktdaten:

danke erst mal ;) Ich glaube ich werde die einfach mal antickern. Die Sache ist ja die, die Idee erst eine Konsolenanwendung zu schreiben und später nen Fenster drum zu machen, finde ich ja gar nicht mal so schlecht ;) Könnte mir so etwas öfters vorstellen, bei Konsolenprogrammen. Die Dinger gibt es in der *nix Welt noch und nöcher, was ich auch supi finde. Kannste mal eben per ssh, alles machen, brauchst nicht mal nen X. Die meisten Tools bekommste ja auch für Windows mit der cygwin dll. Würde an einigen noch gerne nen Fenster drum machen. Dachte eher, es gab da so eine Standartlösung, mal eben die Programme umzubiegen. K3B ( Brennprogramm unter KDE ), setzt auch auf cdrecord (Konsole) auf. Und warum sich den Arsch brechen, wenn die Programme eh schon alle fertig sind ;)
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Hi,
ich muss mich mal an die Diskussion ranhängen. Ich will an diesem Wochenende einen kleinen Frontend für avrdude schreiben damit ich etwas testen kann ohne dauernd die Konsole zu bemühen.

Dafür will ich aber nicht nur die Ausgaben von avrdude in ein Fenster umleiten sondern auch nach Meldungen durchsuchen um eventuell darauf zu reagieren.

Ich habe mir den Thread jetzt noch nicht ganz durchgelesen, aber das werde ich am Wochenende noch tun. Kann ich die Meldungen irgendwie doppelt auswerten oder muss ich das Textfeld durchsuchen lassen? Vielleicht mit einem OnEdit Event oder wie auch immer der heißen mag?
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

burli hat geschrieben:Dafür will ich aber nicht nur die Ausgaben von avrdude in ein Fenster umleiten sondern auch nach Meldungen durchsuchen um eventuell darauf zu reagieren.
Hallo burli!

Kein Problem. Du bekommst den Text jeder Zeile, noch bevor sie in das TextCtrl geschrieben wird.

Das hier z.B. wäre ein guter Einstiegspunkt:

Code: Alles auswählen

    def statuslog_function(self, logentry):
        wx.CallAfter(self.textctrl.AppendText, logentry)
ACHTUNG! Achte darauf, dass diese Funktion im Kontext des Arbeitsthreads ausgeführt wird und nicht im Hauptthread, der für die GUI zuständig ist. Wenn du von hier aus etwas mit der GUI machst, dann musst du dich um Threadtrennung (z.B. mit ``wx.CallAfter``) kümmern. Oder du gehst auf Nummer Sicher und leitest sofort an eine andere Funktion weiter:

Code: Alles auswählen

    def statuslog_function(self, logentry):
        wx.CallAfter(self.threadsafe_statuslog_function, logentry)


    def threadsafe_statuslog_function(self, logentry)
        # logentry prüfen
        #...
        
        # logentry anzeigen
        self.textctrl.AppendText(logentry)
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
The Hit-Man
User
Beiträge: 435
Registriert: Montag 20. Februar 2006, 18:11
Wohnort: Menden / Sauerland
Kontaktdaten:

Auch wenn es hier nicht hingehört, habe ein Beispiel in C# gefunden. Wenn ich extern den cmd.exe ausführe, kann ich auch alles auslesen, allerding wenn ich cdda2wav starte, bleibt das programm beim ReadLine() stehen und kommt da nicht wieder raus :( Also es funtzt auch in C# nur halbwegs:

Code: Alles auswählen

using System;
using System.Windows.Forms;

namespace umleit_2
{
	/// <summary>
	/// Description of Tools.
	/// </summary>
	public class Tools
	{
		public void startExtern ()
		{
			System.Diagnostics.Process Anwendung = new System.Diagnostics.Process(); 
			Anwendung.StartInfo.FileName = ("cdda2wav");
			Anwendung.StartInfo.CreateNoWindow = true;
			Anwendung.StartInfo.RedirectStandardInput = true;
			Anwendung.StartInfo.RedirectStandardOutput = true;
			Anwendung.StartInfo.RedirectStandardError = true;
			Anwendung.StartInfo.UseShellExecute = false;
			Anwendung.Start ();
			
			System.IO.StreamWriter StdIn = Anwendung.StandardInput;
			StdIn.AutoFlush = true;
			
			System.IO.StreamReader StdOut = Anwendung.StandardOutput;
			System.IO.StreamReader StdErr = Anwendung.StandardError;

			string sTemp;
			StdOut.ReadLine();

			//MessageBox.Show(StdOut.ReadLine(), "Befehlszeileninterpreter");
		}
	}
}
The Hit-Man
User
Beiträge: 435
Registriert: Montag 20. Februar 2006, 18:11
Wohnort: Menden / Sauerland
Kontaktdaten:

Lasse ich mir ein Konsolenfenster öffnen, sieht man komischer Weise auch da keine Ausgaben, Programm ist aber im Taskmanager angezeigt :(
The Hit-Man
User
Beiträge: 435
Registriert: Montag 20. Februar 2006, 18:11
Wohnort: Menden / Sauerland
Kontaktdaten:

Beenden sich die externen Programme, bekomme ich alles was ich brauche. Habe es mal mit 7z.exe getestet. Doch dann ist es ja zu spät. Ich brauche die Ausgaben, ja wenn das Programm gerade rennt? wird da irgendetwas gesperrt?
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

The Hit-Man hat geschrieben:Beenden sich die externen Programme, bekomme ich alles was ich brauche. Habe es mal mit 7z.exe getestet. Doch dann ist es ja zu spät. Ich brauche die Ausgaben, ja wenn das Programm gerade rennt? wird da irgendetwas gesperrt?
Klingt nicht nach gesperrt sondern gebuffert. Der Buffer wird geleert wenn das Programm beendet wird
BlackJack

Nur mal so als Anregung: Kann es sein, dass die `cdda2wav`-Programmierer schon daran gedacht haben, dass man das Programm von einer GUI aus verwenden könnte!? Ich tippe mal stark darauf, dass die Ausgaben auf stderr ausgegeben werden und Du einfach an der falschen Pipe auf Daten wartest.
The Hit-Man
User
Beiträge: 435
Registriert: Montag 20. Februar 2006, 18:11
Wohnort: Menden / Sauerland
Kontaktdaten:

Also dafür ausgelegt, sollte es ja sein, gibt ja diese --gui Option dabei. Ich habe aber genau das selber Problem mit 7z ( ist ja nen Packer ). Auch da bekomme ich erst was zurück, wenn es fertig ist. Das kann doch eigentlich nicht sein. Gibt doch ganz viele GUIs, die nur auf einem Komandozeilen Tool aufsetzen und trotzdem locker nen ProgressBar anzeigen lassen können. Jetzt sitze ich da schon 2-3 Tage dran. Bin bald echt fertig, mit den Nerven ;)
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Ich habe jetzt einfach mal stumpf ein Beispiel aus wxPython in Action abgetippt und hab mit os.system() das Programm avrdude gestartet. Ohne Parameter gibt es einfach die Optionen aus.

Code: Alles auswählen

#!/usr/bin/env python
import wx
import sys
import os

class Frame(wx.Frame):
    def __init__(self, parent, id, title):
        print "Frame __init__"
        wx.Frame.__init__(self, parent, id, title)
        
class App(wx.App):
    def __init__(self, redirect=True, filename=None):
        print "App __init__"
        wx.App.__init__(self, redirect, filename)
    def OnInit(self):
        print "OnInit"      #Writing to stdout
        self.frame = Frame(parent=None, id=-1, title='Startup')            
        self.frame.Show()                                                  
        self.SetTopWindow(self.frame)
        print >> sys.stderr, "A pretend error message"      
        os.system("avrdude")    
        return True
    def OnExit(self):
        print "OnExit"
if __name__ == '__main__':
    app = App(redirect=True)
    print "before MainLoop"
                               
    app.MainLoop()    
    print "after MainLoop"
Das Ergebnis: Die eigentliche Ausgabe vom Programm kommt im Fenster an, die Ausgabe von avrdude landet ganz normal in der Konsole.
The Hit-Man
User
Beiträge: 435
Registriert: Montag 20. Februar 2006, 18:11
Wohnort: Menden / Sauerland
Kontaktdaten:

ja so weit, war ich ja auch schon. Aber nehm einfach mal den 7z Packer und laß den was zusammen packen ( etwas großes, wo er viel zu tun hat ). Du wirst erst etwas zurück bekommen, wenn er fertig geowrden ist. EHER leider nicht :( und ich brauche eben die Werte, die er gerade beim Arbeiten aus gibt.
Antworten