Problem mit threading

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.
Antworten
xturbo77
User
Beiträge: 39
Registriert: Montag 9. September 2002, 20:05
Kontaktdaten:

Folgdens Problem: ich möchte alle paar Minuten via poplib meine mails checken. Da das ganze über eine kleine GUI konfigurierbar sein soll muss dies wohl in einem eigenen Thread ablaufen.
Ich dachte mir ich leite mir eine Klasse von threading.Thread ab und überschreibe die run Methode. In der run Methode läuft der Mailabruf in einer Endlosschleifen mit timer.

Code: Alles auswählen

import poplib,  time, threading

class fetchmail(threading.Thread):
    def __init__(self,  host, user, pw):
        self.host = host
        self.user = user
        self.pw = pw
        self.lock = threading.Lock()
        
    def run(self):
       while 1:
            try:
                self.lock.acquire()
                self.mailbox = poplib.POP3(host)
                self.mailbox.user(user)
                self.mailbox.pass_(pw)
                self.msg = self.mailbox.list()[0]
                print self.msg
                
                self.lock.release()
                time.sleep(1000)
            except:
                print 'pop3 error'

    
if __name__ == "__main__":
    m = fetchmail("pop.gmx.net","mustermann@gmx.de","trustno1")
    m.start()

Und so sieht die Fehlermeldung aus (mit der ich momentan nix anfangen kann):

Code: Alles auswählen

Traceback (most recent call last):
  File "C:\PythonScripts\pop3.py", line 36, in ?
    m = fetchmail("pop.gmx.net","muster@gmx.de","trustno1")
TypeError: __init__() takes exactly 5 arguments (4 given)
Hmmm, was mache ich falsch? hab mit Threads kaum Erfahrungen :cry:
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

du überschreibst die init-Methode von threading.Thread. Das ist nicht so günstig, da hier ja der eigentliche Thread, den die Klasse repräsentiert, initialisiert wird. Probier mal dafür halt eine zusätzliche Methode statt der init zu definieren:

Code: Alles auswählen

class fetchmail(threading.Thread): 
    def initialisiere(self,  host, user, pw): 
        self.host = host 
        self.user = user 
        self.pw = pw 
        self.lock = threading.Lock()
...

if __name__ == "__main__": 
    m = fetchmail()
    m.initialisiere("pop.gmx.net","mustermann@gmx.de","trustno1")
    m.start()
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hi Milan,

ersmal fällt mir auf, daß die Methode in der Classendefinition run heisst und du dann m.start aufrufst.
Wenn Du ohnehin mit einer GUI arbeiten willst, stellt praktisch jedes GUI-Interface eine Möglichkeit zur Verfügung, timergesteuerte Funktionen und/oder Idle-Funktionen einzubinden. Ist sicher einfacher als mit Tasks zu arbeiten.


Gruß

Dookie
xturbo77
User
Beiträge: 39
Registriert: Montag 9. September 2002, 20:05
Kontaktdaten:

Milan hat geschrieben:du überschreibst die init-Methode von threading.Thread. Das ist nicht so günstig, da hier ja der eigentliche Thread, den die Klasse repräsentiert, initialisiert wird. Probier mal dafür halt eine zusätzliche Methode statt der init zu definieren:

Code: Alles auswählen

class fetchmail(threading.Thread): 
    def initialisiere(self,  host, user, pw): 
        self.host = host 
        self.user = user 
        self.pw = pw 
        self.lock = threading.Lock()
...

if __name__ == "__main__": 
    m = fetchmail()
    m.initialisiere("pop.gmx.net","mustermann@gmx.de","trustno1")
    m.start()
Krass hab in letzten zuviel Java programmiert :oops:

@Dookie
Falls du einen besseren Lösungsansatz kennst, lass es mich wissen.
Die Methode start ruft auch wiederum die run auf.
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

sorry, meinte oben natürlich xturbo77 und ned Milan :)

Ich arbeite meistens mit gtk2, hier etwas aus der Doku dazu
gtk2-Timeouts und Idlefunctions
Andere GUIs stellen sicher vergleichbare Mechanismen zur Verfügung.


Dookie
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Der Vorschlag von Dookie ist bestimmt nicht dumm, aber nur zur Vollständigkeit halber die einfachere Variante (die ich vorhin einfach vergessen hatte). Einfach die ungebundene Init-Methode von Thread intern rufen.

Code: Alles auswählen

class fetchmail(threading.Thread): 
    def __init__(self,  host, user, pw):
        threading.Thread.__init__(self)
...
xturbo77
User
Beiträge: 39
Registriert: Montag 9. September 2002, 20:05
Kontaktdaten:

Und schon das nächste Problem.
Der Hauptthread läuft jetzt (dank Milan). Jetzt soll dieser Thread wiederrum einen Thread starten.
Hmmm, geht das überhaupt? Was hats eigentlich exakt mit diesem Lock aufsich? Brauche ich das zwingend?
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Das mit dem Thread im Thread... ausprobieren, aber warum sollte es nicht gehen? Kannst ja für einzelne Funktionen auch die Funktion Thread.start_new_thread(funk,arg,kargs) nehmen (Thread ist hier ein anderes Modul) Nur wofür brauchst du das? Um mehrere Accounts gleichzeitig abzurufen?

Tja, und was es mit den locks auf sich hat kann ich dir nicht genau sagen, weil ich sie noch nie ernsthaft gebraucht habe und deswegen den teil der Doku nur überflogen hab. Ich glaube, du kannst Objekte uas dem Hauptprogramm gegen Mehrfachzugriff schützen (bei mehreren Threads), will mich aber mal nicht festlegen.
xturbo77
User
Beiträge: 39
Registriert: Montag 9. September 2002, 20:05
Kontaktdaten:

ich nochmal....

das problem ist dass der Thread eigentlich permanent laufen soll und alle paar Minuten eine pop3 antrage macht und dann ein Popup Window mit dem Ergebnis darstellen soll. Leider reagiert das Window leider nicht bzw existiert nur solange der thread läuft! :?
Deshalb ich dachte ich mache einen extra Thread für das Popup für jedesmal wenn eine email gefunden wurde. Leider existiert dieses Popup auch nur für die Lebensdauer des UnterThreads. Wie kann ich das umgehen???

Code: Alles auswählen

import poplib,  time, threading

class fetchmail(threading.Thread):
    def __init__(self, master, host, user, pw):
        threading.Thread.__init__(self)
        self.host = host
        self.user = user
        self.pw = pw
        self.master = master
        self.lock = threading.Lock()
        
    def run(self):
        #while 1:

            print "MainThread started...."
            self.lock.acquire()
            print "MainThread locked"
            self.mailbox = poplib.POP3(self.host)
            self.mailbox.user(self.user)
            self.mailbox.pass_(self.pw)
            print self.host, self.user
            self.msg = self.mailbox.list()[0]
            print self.msg
            numMessages = len(self.mailbox.list()[1])

            self.master.showMessage(self.msg) #Popup Message
            
            self.lock.release()
            print "MainThread unlocked"

            time.sleep(10) #Popup ist für 10 Sek sichtbar
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Hmm, eher ein GUI Prob ;).Öffne das Fenster doch mit der Initialisierung von fetchmail und verstecke es gleich mit withdraw. wenn dein Thread dann eine Mail findet macht er es wieder sichtbar, bis der Benutzer es schließt (nur wieder versteckt), weil er es nicht mehr braucht...
xturbo77
User
Beiträge: 39
Registriert: Montag 9. September 2002, 20:05
Kontaktdaten:

Milan hat geschrieben:Hmm, eher ein GUI Prob ;).Öffne das Fenster doch mit der Initialisierung von fetchmail und verstecke es gleich mit withdraw. wenn dein Thread dann eine Mail findet macht er es wieder sichtbar, bis der Benutzer es schließt (nur wieder versteckt), weil er es nicht mehr braucht...
Gute Idee! Klappt ganz gut. Verstecke das Popup Fenster zunächst, falls eine Mail gefunden wird, wird der Text des Popups neu gesetzt und sichtbar gemacht.
Trotzdem werd ich mich noch nach ner anderen Möglichkeit umschauen. Dookie hat recht, wxPython bieten da bestimmt ganz andere Möglichkeiten. Leider hab ich vor paar Tagen zum ersten mal was damit gemacht, so dass ich von der vielzahl der Klassen noch etwas erschlagen bin. :roll:
Hätte auch gerne Tkinter benutzt. Ist es mit Tkinter möglich ein Icon mit Kontextmenü im SysTray anzuzeigen und "always on top" Fensterelemete zu erstellen?
Antworten