Seite 1 von 1
Funktion in ÜberKlasse aufrufen
Verfasst: Freitag 8. Juni 2007, 09:15
von HarryPython
Hi
Ich habe folgendes Problem:
Ich hab zwei .py Dateien. In der einen die Klasse Main und in der anderen die Klasse Thread. Die Klasse Thread importiere ich mit 'from Thread import Thread' in die Klasse Main.
In Main habe ich einen Button der in Thread eine Funktion startet. Durch zb: self.test=Thread(self)
self.test.start()
Nun möchte ich dass wenn meine Funktion in der Klasse Thread durchlaufen ist die Eigenschaft des Buttons Label, der in meiner KlasseMain steht, ändern.
Ist es nicht möglich aus der Klasse Thread eine Funktion in der Klasse Main aufzurufen???? Wenn ich sowas wie oben in die Klasse Thread schreibe kennt er immer meine Klasse Main nicht. Arrrr.
Wahrscheinlch hab ich das mit Ober und Unterklassen noch nicht ganz verstanden
Hoffe es kann mir jemand Helfen. Danke!
Re: Funktion in ÜberKlasse aufrufen
Verfasst: Freitag 8. Juni 2007, 10:33
von gerold
Hallo HarryPython!
HarryPython hat geschrieben:Ich hab zwei .py Dateien. In der einen die Klasse Main und in der anderen die Klasse Thread.
1.) Das sind sehr unglücklich gewählte Namen. Sie sagen nichts aus.
2.) Warum teilst du dein Programm in mehrere Dateien auf? Funktioniert eines der Module auch ohne das andere Modul? Wenn nicht, dann verkompliziert eine Aufteilung dein Programm unnötig.
HarryPython hat geschrieben:In Main habe ich einen Button der in Thread eine Funktion startet. Durch zb:
Nun möchte ich dass wenn meine Funktion in der Klasse Thread durchlaufen ist die Eigenschaft des Buttons Label, der in meiner KlasseMain steht, ändern.
Du hast uns nicht gesagt, mit welchem Toolkit du deinen Button erstellt hast. Für Tkinter, wxPython und Co. gibt es eigene Unterforen.
HarryPython hat geschrieben:Ist es nicht möglich aus der Klasse Thread eine Funktion in der Klasse Main aufzurufen???? Wenn ich sowas wie oben in die Klasse Thread schreibe kennt er immer meine Klasse Main nicht.
Nein, von einem Thread aus, **direkt** eine Funktion in einem anderen Thread (auch das Hauptprogramm läuft in einem Thread) aufzurufen, geht nicht.
Unter wxPython wird diese Trennung z.B. mit wxPython-Events umgangen. Z.B. über die Funktion ``wx.CallAfter()``
mfg
Gerold

Verfasst: Samstag 9. Juni 2007, 12:07
von HarryPython
Hi Gerold.
Erstmal Danke für die schnelle Antwort. Echt klasse dieses Forum. Hatte nur ein Paar Probleme mit dem Anmelden. Als ich all meine Daten eingegeben hab kam eine Fehlermeldung danach konnte ich mich nicht nochmal anmelden, da die E-Mail Adresse schon regestriert ist. Mit der 3.Mail hat es dann geklappt. Vielleicht weißt du ja bereits wovon ich rede. Aber jetzt ist er drin. Jupi.
zum Thema:
Hab sie nur hier Main und Thread genannt zum leichteren Verständniss.
Warum aufteilen ist eine gute Frage. Als ich noch nicht wußte wie man Threads erstellt hab ich so mein Problem gelöst.
Ich arbeite mit wx.
Nein, von einem Thread aus, **direkt** eine Funktion in einem anderen Thread (auch das Hauptprogramm läuft in einem Thread) aufzurufen, geht nicht.
Aber ich starte ja auch aus Main mit start() meine Funktion run() in Thread. Oder ist das die einziege Ausnahme?
mfg Harry
Verfasst: Samstag 9. Juni 2007, 12:17
von BlackJack
Du startest mit `start()` einen neuen Thread und *der* ruft dann die `run()`-Methode auf. Das ist in der Tat eine Ausnahme weil die `start()`-Methode etwas sehr "magisches" tut: einen neuen Thread starten und sofort zum Aufrufer zurückkehren.
Verfasst: Sonntag 10. Juni 2007, 20:09
von HarryPython
Hilfe!!!!
Sitze jetzt seit drei Tagen an dem Problem und dreh langsam durch.
Ich hab die beiden Klassen zusammengefügt.
Hab es auch schon geschafft aus meinem Thread eine Funktion in Main aufzurufen. Irgendwelche print Anweisungen in dieser Funktion klappen aber sobald ich sage er soll das Label von meinem Button ändern ignoriert er das einfach. Gibt nicht mal ein Fehler.
wx.CallAfter liefert eine Fehlermeldung "NoneType Objekt not callable" führt dann aber dennoch die Funktion aus aber auch nur so als würde ich sie direkt aufrufen.
Ich möchte doch nur bei meinem Button in der Klasse Main das Label wieder auf "Start" setzen wenn der Tread zuende ist!!!!!!!!!!!!!!!!!
Damit der User sieht er kann den Thread wieder starten.
HILFE wo sind die Programmierer????
Verfasst: Sonntag 10. Juni 2007, 20:31
von Sr4l
Du könntest mal dein Code posten bei:
http://paste.pocoo.org/ und uns den Link sagen.
dann kann ich den Wikieintrag mit einem sehr großen Beispiel empfehlen [wiki]Threading Beispiel1[/wiki] wobei ich es etwas zu lang finde,
Code: Alles auswählen
#! /usr/bin/env python
#-*- coding: latin-1 -*-
#
import socket,time,thread
def Server(byte,host,port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #Socket defenieren
sock.bind((host, port)) #server auf localhost, Port 12345 laufen lassen
sock.listen(1) #Server maximal 1 Client akzeptieren lassen
conn, addr = sock.accept()
while True:
#print addr," ",data
print "<<<: %s"%(conn.recv(byte))
conn.close()
def Run():
host = "localhost" #Hostname
port = 12345 #Verbindungs Port
byte = 1024 #Byte Groesse
#
thread.start_new_thread(Server, (byte,host,port)) #Lässt Server() im Hintergrundlaufen
while True:
print "Der Server blockt mich nicht dank dem Thread."
time.sleep(2) #Nur damit wir keine 100% CPU Auslastung haben
Run()
Das war der kürzeste Code zum Modul Thread den ich auf meiner Festplatte noch gefunden habe, ich bitte um Verzeihung der nicht PEP8 konformen Schreibweise
Wegen deinem Button Problem: Wenn keine Fehlermeldung kommt gibt es keine Fehler, ohne Code schwierig zusagen was da nicht geht.
Verfasst: Sonntag 10. Juni 2007, 21:52
von gerold
HarryPython hat geschrieben:Ich möchte doch nur bei meinem Button in der Klasse Main das Label wieder auf "Start" setzen wenn der Tread zuende ist!
Hallo HarryPython!
Nicht so kompliziert, aber mit weniger Möglichkeiten:
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
import wx
import thread
import time
wx.SetDefaultPyEncoding("iso-8859-15")
class MyFrame(wx.Frame):
def __init__(
self, parent = None, id = -1, title = "Example", size = wx.Size(200, 150)
):
wx.Frame.__init__(self, parent, id, title, size = size)
self.panel = wx.Panel(self)
vbox_main = wx.BoxSizer(wx.VERTICAL)
self.panel.SetSizer(vbox_main)
vbox_main.AddStretchSpacer()
self.btn_start = wx.Button(self.panel, label = "Start")
vbox_main.Add(self.btn_start, 0, wx.ALL | wx.ALIGN_CENTER)
self.btn_start.Bind(wx.EVT_BUTTON, self.start_worker)
vbox_main.AddStretchSpacer()
self.panel.Layout()
def start_worker(self, event = None):
self.btn_start.SetLabel("working...")
self.btn_start.Disable()
self.panel.Layout()
wx.SafeYield()
thread.start_new_thread(self.worker, ())
def worker(self):
for i in xrange(5):
print "Ich arbeite..."
time.sleep(1)
# Fertig
wx.CallAfter(self.btn_start.SetLabel, "Start")
wx.CallAfter(self.btn_start.Enable)
wx.CallAfter(self.panel.Layout)
wx.SafeYield()
def main():
"""Testing"""
app = wx.PySimpleApp()
f = MyFrame()
f.Center()
f.Show()
app.MainLoop()
if __name__ == "__main__":
main()
Komplizierter, aber mehr Möglichkeiten:
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
import wx
import time
import threading
wx.SetDefaultPyEncoding("iso-8859-15")
class MyWorker(threading.Thread):
def __init__(self, finished_function = None):
threading.Thread.__init__(self)
self.canceled = threading.Event()
self.finished_function = finished_function
def run(self):
for i in xrange(10):
if self.canceled.isSet():
print "Gestoppt..."
break
print "Ich arbeite..."
time.sleep(1)
if self.finished_function:
self.finished_function()
def stop(self):
self.canceled.set()
class MyFrame(wx.Frame):
def __init__(
self, parent = None, id = -1, title = "Example", size = wx.Size(200, 150)
):
wx.Frame.__init__(self, parent, id, title, size = size)
self.worker = None
self.panel = wx.Panel(self)
vbox_main = wx.BoxSizer(wx.VERTICAL)
self.panel.SetSizer(vbox_main)
vbox_main.AddStretchSpacer()
self.btn_start = wx.Button(self.panel, label = "Start")
vbox_main.Add(self.btn_start, 0, wx.ALL | wx.ALIGN_CENTER)
self.btn_start.Bind(wx.EVT_BUTTON, self.start_worker)
self.btn_cancel = wx.Button(self.panel, label = "Abbruch")
self.btn_cancel.Disable()
vbox_main.Add(self.btn_cancel, 0, wx.ALL | wx.ALIGN_CENTER)
self.btn_cancel.Bind(wx.EVT_BUTTON, self.cancel_worker)
vbox_main.AddStretchSpacer()
self.panel.Layout()
def start_worker(self, event = None):
self.btn_start.SetLabel("working...")
self.btn_start.Disable()
self.btn_cancel.Enable()
self.panel.Layout()
wx.SafeYield()
self.worker = MyWorker(self.worker_finished)
self.worker.start()
def cancel_worker(self, event = None):
self.worker.stop()
def worker_finished(self):
wx.CallAfter(self.btn_start.SetLabel, "Start")
wx.CallAfter(self.btn_start.Enable)
wx.CallAfter(self.btn_cancel.Disable)
wx.CallAfter(self.panel.Layout)
wx.SafeYield()
def main():
"""Testing"""
app = wx.PySimpleApp()
f = MyFrame()
f.Center()
f.Show()
app.MainLoop()
if __name__ == "__main__":
main()
mfg
Gerold
PS: Schon spät... wenig Kommentare!
Verfasst: Montag 11. Juni 2007, 09:10
von HarryPython
Ahhhhhhhhhhhhhhhhhhhhhhhhhh.
Genau das hab ich gesucht!!!!!!!!!!!!!
Danke Meister Gerold!!!!!!!!!!!!!!
Die ganze Funktion an den Thread übergeben.

Na klar.
Cool. Danke nochmal. Jetzt kann ich weiter machen.
mfg Padawan HarryPython