Seite 1 von 1

Streamripper GTK Frontend

Verfasst: Samstag 20. Dezember 2008, 12:37
von alfonsospringer
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?

Verfasst: Samstag 20. Dezember 2008, 12:49
von Leonidas
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.

Verfasst: Samstag 20. Dezember 2008, 13:08
von alfonsospringer
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?

Verfasst: Samstag 20. Dezember 2008, 14:50
von 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.

Verfasst: Samstag 20. Dezember 2008, 15:18
von Leonidas
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.

Verfasst: Samstag 20. Dezember 2008, 19:13
von alfonsospringer
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")

Verfasst: Samstag 20. Dezember 2008, 19:35
von Leonidas
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.

Verfasst: Samstag 20. Dezember 2008, 19:45
von cofi
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.

Verfasst: Samstag 20. Dezember 2008, 19:46
von alfonsospringer
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.

Verfasst: Samstag 20. Dezember 2008, 20:26
von veers
http://29a.ch/httpripper/, da könntest du dir das sonst auch abschauen. :wink:

Gruss,
Jonas

Verfasst: Samstag 20. Dezember 2008, 20:30
von alfonsospringer
So eine hilfreiche Seite findet man selten ;)

Bild

Verfasst: Samstag 20. Dezember 2008, 20:34
von cofi
Dann schau doch mal auf http://29a.ch/httpripper/ Die soll viel besser sein ;)

Verfasst: Samstag 20. Dezember 2008, 21:00
von alfonsospringer
Nettes Programm! Werd mir den ungebdingt Source mal ansehen.