Streamripper GTK Frontend

Programmierung für GNOME und GTK+, GUI-Erstellung mit Glade.
Antworten
alfonsospringer
User
Beiträge: 34
Registriert: Sonntag 24. August 2008, 21:50

Als Testprojekt für PyGTK habe wollte ich ein kleines GUI Frontend für das Konsolenprogramm Streamripper schreiben. Bisher funktioniert es auch bis auf einen kleinen Fehler prima. Ich muss den Startknopf immer mehrfach drücken, bevor das Programm mit dem Rippen beginnt. Nachdem ich den Knopf zweimal gedrückt habe startet das Programm aber auch zweimal... Nur bei einfachem drücken passiert nichts

Das Glade Gui besteht aus zwei Texteingabezeilen und einen Knopf. Der Knopf hat ein callback namens go an seinem clicked Signal.

Code: Alles auswählen

#!/usr/bin/python
import sys, os, threading


try:
     import pygtk
     pygtk.require("2.0")
except:
      pass
try:
    import gtk
    import gtk.glade
except:
    sys.exit(1)


class streamripper(threading.Thread):
    def __init__(self, cmd):
        threading.Thread.__init__(self) 
        self.command = cmd
        print "Streamripper Object created"
        self.start()
        print "Streamripper started"
        
    def run(self):
        os.system(self.command)
   

class streamrippergui:
    def __init__(self):
        self.gladefile = "/home/robert/eclipse/Python/Streamripper_GTK_Frontend/gui.glade"  
        self.wTree = gtk.glade.XML(self.gladefile) 
        self.url = self.wTree.get_widget("streamurl")
        self.location = self.wTree.get_widget("saveplace")
        
        dic = { "go" : self.go, "kill" : self.destroy}
        self.wTree.signal_autoconnect(dic)
        
    def destroy(self, widget, data=None):
        gtk.main_quit()

    def go(self, param=None):
        self.command = str("streamripper "+self.url.get_text()+" -d "+ self.location.get_text()) 
        self.ripper = streamripper(self.command)
            
if __name__ == "__main__":
    gui = streamrippergui()
    gtk.main()
    os.system("killall streamripper")
    del gui
Könnt ihr mir erklären, was da nicht stimmt?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Naja, ich muss ja sagen, dass ich den Ansatz ja mal relativ fürchterlich finde aus zig Gründen. Aber den Thread aus ``__init__`` zu starten klingt wie eine schlechte Idee, die zu Problemen führen könnte.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
alfonsospringer
User
Beiträge: 34
Registriert: Sonntag 24. August 2008, 21:50

Damit, das ihr den Ansatz fürchterlich findet hatte ich ja schon gerechnet. Die Sache mit dem Thread ists aber nicht. Habe das start() grade ans Ende der go() Methode verlegt.

Könntest du/ihr mir vielleicht zusätzlich noch einen Hinweis geben, wie ihr einen weniger fürchterlichen Ansatz implementieren würdet?
BlackJack

@alfonsospringer: Mit den ``except``\s ohne konkrete Ausnahme "verschluckst" Du jegliche Information, die man zur Fehlersuche verwenden könnte. Selbst ein Endanwender wird überhaupt nicht informiert *warum* das Programm nicht starten konnte.

Die Klassennamen halten sich nicht an die Namenskonvention.

`streamripper` als Klasse ist unnötig kompliziert. Eine Funktion hätte es auch getan.

Statt `os.system()` sollte man lieber das `subprocess`-Modul verwenden. Damit erspart man sich wahrscheinlich den eigenen Thread selber erzeugen und starten zu müssen, und die ganzen Probleme, die durch den Umweg über eine Shell entstehen.

So ein ``killall`` halte ich für problematisch, da das auch Prozesse beträfe, die nicht von der GUI gestartet wurden. Ein Programm, das einfach Prozesse nach Namen killt, würde mich jedenfalls extrem aufregen, wenn mir das zum Beispiel eine per `cron` gestartete Aufnahme einfach so beendet.

Das ``del gui`` am Ende ist überflüssig.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

BlackJack hat geschrieben:Statt `os.system()` sollte man lieber das `subprocess`-Modul verwenden. Damit erspart man sich wahrscheinlich den eigenen Thread selber erzeugen und starten zu müssen, und die ganzen Probleme, die durch den Umweg über eine Shell entstehen.
Und das zusammenbauen der Argumente über Strings.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
alfonsospringer
User
Beiträge: 34
Registriert: Sonntag 24. August 2008, 21:50

Ich habe die exceptions jetzt noch ein wenig ausgeweitet, um einen möglichen Fehler einzugrenzen, aber es wird keine der exceptions getriggert.

Code: Alles auswählen

#!/usr/bin/python
import sys, os, threading


try:
     import pygtk
     pygtk.require("2.0")
     print "PyGTK imported"
except:
     print "Falsche PyGTK Version"
try:
    import gtk
    import gtk.glade
except:
    sys.exit(1)


class Streamripper(threading.Thread):
    def __init__(self, cmd):
        threading.Thread.__init__(self) 
        self.command = cmd  
        
    def run(self):
        try:
        	os.system(self.command)  
        	print "Rippen begonnen"
        except:
        	print "Kann Ripper nicht starten"

class Streamrippergui(object):
    def __init__(self):
        self.gladefile = "/home/robert/eclipse/Python/Streamripper_GTK_Frontend/gui.glade"  
        self.wTree = gtk.glade.XML(self.gladefile) 
        self.url = self.wTree.get_widget("streamurl")
        self.location = self.wTree.get_widget("saveplace")
        
        dic = { "on_button1_clicked" : self.on_button1_clicked, "kill" : self.destroy}
        self.wTree.signal_autoconnect(dic)
        
    def destroy(self, widget, data=None):
        gtk.main_quit()

    def on_button1_clicked(self, param=None):
        self.command = str("streamripper "+self.url.get_text()+" -d "+ self.location.get_text()) 
        try:
        	self.ripper = Streamripper(self.command)
        	print "Objekt erstellt"
        except:
        	print "Kann Objekt nicht erstellen"
        try:
        	self.ripper.start()
        	print "Thread gestartet"
        except:
        	print "Kann thread nicht starten!"  
            

if __name__ == "__main__":
    gui = Streamrippergui()
    gtk.main()
    os.system("killall streamripper")
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Lass doch einfach mal das ganze Exception-Handling weg. Du catchst ständig alle Exceptions, das ist sowieso genau das was man eben nicht machen sollte.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Wenn du die exceptions nicht abfängst, solltest du doch einen Traceback für die exceptions bekommen.
Außerdem könntest du mal BJs und Leonidas' Einwände in deinem Code berücksichtigen.
alfonsospringer
User
Beiträge: 34
Registriert: Sonntag 24. August 2008, 21:50

Die PyQT Version, die ich von diesem Programm zuvor geschrieben habe, die bis auf das GUI völlig identisch ist funktioniert prima. Wie kann das sein?


LÖSUNG:

Ich habe grade noch ein wenig gesucht und im PyGTK FAQ rausgefunden, dass man wenn man in einem Programm, das PyGTK benutzt, Threads verwenden möchte, man immer vor dem Aufruf von gtk.main() die Funktion gtk.gdk.threads_init() aufrufen muss. Dann klappt es. Ich weiss zwar nicht warum, aber so ist es. Sonst kanns nicht richtig klappen.
Benutzeravatar
veers
User
Beiträge: 1219
Registriert: Mittwoch 28. Februar 2007, 20:01
Wohnort: Zürich (CH)
Kontaktdaten:

http://29a.ch/httpripper/, da könntest du dir das sonst auch abschauen. :wink:

Gruss,
Jonas
[url=http://29a.ch/]My Website - 29a.ch[/url]
"If privacy is outlawed, only outlaws will have privacy." - Phil Zimmermann
alfonsospringer
User
Beiträge: 34
Registriert: Sonntag 24. August 2008, 21:50

So eine hilfreiche Seite findet man selten ;)

Bild
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Dann schau doch mal auf http://29a.ch/httpripper/ Die soll viel besser sein ;)
alfonsospringer
User
Beiträge: 34
Registriert: Sonntag 24. August 2008, 21:50

Nettes Programm! Werd mir den ungebdingt Source mal ansehen.
Antworten