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.
Es wird keine Exception geworfen, weil get so lange blockiert, bis wieder was in der Queue ist. Sinn solcher Threads ist es, das sie Aufgaben abarbeiten, die z.b. von Nutzern der GUI ausgelöst werden.
Danke dir, habe das mit der python doku [1] nachvollziehen können (block=True).
D.h. der thread läuft die ganze Zeit,bis der Prozess (Anwendung) beendet wird. Ein daemon=True wäre hier fatal,richtig?
Kann man den Thread dann irgendwie beenden? Muss vermutlich in der klasse eine Abbruchbedingung setzen,welche innerhalb der "while true" schleife geprüft wird (setzt natürlich vorraus,dass die position noch erreicht wird,da evtl.bei get hängt)...ein thread.stop habe ich noch nicht gefunden.evtl.ist der sauberste Weg,die "Abbruchbedingung" auch in die queue zu schicken dann wird get getriggert und kann die Schleife verlassen und den thread beenden.
@frank-w: Warum sollte ein ``daemon=True`` fatal sein? Das sollte man eigentlich fast immer machen. Es gibt eher wenige Fälle wo man das nicht machen möchte, weil in den meisten Fällen es einfach nur nervig ist wenn Prozesse von aussen gekillt werden müssen weil das Hauptprogramm zwar eigentlich beendet werden sollte, es aber Threads gibt, die das Ende verhindern.
Abbruchbedingung über die Queue wenn da noch irgendwie auf den Abbruch reagiert werden soll, bevor es tatsächlich abbricht. Ansonsten reicht ``daemon=True`` und beenden des Hauptprogramms.
“Ich bin für die Todesstrafe. Wer schreckliche Dinge getan hat, muss eine angemessene Strafe bekommen. So lernt er seine Lektion für das nächste Mal.” — Britney Spears, Interview in der französischen Zeitung Libération, 2. April 2002
Daemon=true sorgt ja dafür (wenn ich es richtig verstehe) dass der thread weiterläuft,wenn das hauptprogramm beendet wird,bis der Thread fertig ist. Wenn ich while true mache und queue.get auf weitere daten wartet,läuft der Thread doch ewig weiter,oder nicht? Also grob das Szenario,was du ansprichst...
Oder wird die queue dann zerstört und damit der Thread beendet?
@frank-w Du hast `daemon` genau falsch herum verstanden. Wenn man das auf `True` setzt, dann läuft der Thread gerade *nicht* weiter wenn das Hauptprogramm beendet wird, sondern wird mit dem Hauptprogramm beendet.
“Ich bin für die Todesstrafe. Wer schreckliche Dinge getan hat, muss eine angemessene Strafe bekommen. So lernt er seine Lektion für das nächste Mal.” — Britney Spears, Interview in der französischen Zeitung Libération, 2. April 2002
__blackjack__ hat natuerlich recht, ich finde den Begriff und die Semantik aber tatsaechlich auch verwirrend. Ein Daemon laeuft an sich ja unabhaengig von anderen Systemteilen, aber hier dann nicht, sondern er wird eben gestoppt. Wohingegen er munter weiterlaeuft, wenn daemon=False... finde ich ungluecklich.
Danke euch...habe es wirklich andersherum (vom losgelösten prozess unter linux) verstanden...die doku ist da ein bisschen verwirrend (doppelte Verneinung)
Ich habe es jetzt so (self.workthread wird im init der Klasse auf None gesetzt):
def worker(self):
while True:
item = self.q.get()
self.scrolltxt.insert(tk.END, str(item)+ '\n')
self.q.task_done()
sleep(1)
def createthread(self):
if not self.workthread or not self.workthread.is_alive():
self.workthread=Thread(target=self.worker,daemon=True)
self.workthread.start()
def clickme(self,num=0):
c1=num
c2=num+30
for item in range(c1,c2):
self.q.put(item)
self.createthread()
Ist natürlich exemplarisch...es füllt die queue einmal vor dem start des threads und beim zweiten klick ist der thread noch aktiv (wird nicht nochmal gestartet) und da wird nur die queue gefüllt
@frank-w: Der Code wäre ein bisschen einfacher wenn Du den Thread schon in der `__init__()` erstellst und startest. Solange der in `get()` hängt, verbraucht der keine Rechenzeit.
Edit: Argh: Gerade gesehen: Der Thread ändert was in der GUI — das ist falsch. Die darfst Du nur von dem Thread aus verändern, in dem die GUI-Hauptschleife läuft.
“Ich bin für die Todesstrafe. Wer schreckliche Dinge getan hat, muss eine angemessene Strafe bekommen. So lernt er seine Lektion für das nächste Mal.” — Britney Spears, Interview in der französischen Zeitung Libération, 2. April 2002
Das Ändern in der gui vom thread aus habe ich grob aus einem Beispiel (buch)...wie bekommt die gui mit,dass der thread was gemacht hat,ohne zu blockieren? Über eine 2.queue (get würde halt die gui blockieren,genauso wie eine schleife zum pollen dieser)?
Betreffend der gelöst-Kennzeichnung habe ich die grünen Haken bei den anderen Themen gesehen und wollte mich dran halten,da es in anderen Foren zum "guten Ton" gehört
@frank-w: Man pollt üblicherweise eine Queue mit einer Methode und `Widget.after()`.
“Ich bin für die Todesstrafe. Wer schreckliche Dinge getan hat, muss eine angemessene Strafe bekommen. So lernt er seine Lektion für das nächste Mal.” — Britney Spears, Interview in der französischen Zeitung Libération, 2. April 2002
Wenn ich pause_and_empty nach dem Füllen der queue aufrufe, müsste das passen,oder? Brauche ich das pause oder reicht das Abfragen,ob die queue leer ist? self.parent muss dann vermutlich der button sein,der die queue gefüllt hat,oder?
@frank-w: `self.parent` muss *irgendein* `Widget` sein. Welche ist egal. Diese `pause_and_empty()`-Methode brauchst Du IMHO überhaupt nicht. Der Code da ist komisch und unübersichtlich und die Frage ist mit -1 bewertet und es gibt auch keine richtige Antwort.
“Ich bin für die Todesstrafe. Wer schreckliche Dinge getan hat, muss eine angemessene Strafe bekommen. So lernt er seine Lektion für das nächste Mal.” — Britney Spears, Interview in der französischen Zeitung Libération, 2. April 2002
Kannst du mir vielleicht ein besseres beispiel geben? Der sinn an der funktion ist ja die rekursion...also wenn bei einer prüfung noch was in der queue drin ist,wird nochmal gewartet.
Auch wenn ich das mit dem sys.exit nicht ganz nachvollziehen kann...self.running wird ja nur in endApplication auf 0 gesetzt,welches nie aufgerufen wird
Ja das mit dem `exit()` ist schräg, da würde man einfach per `quit()` auf dem passenden Objekt die `mainloop()` verlassen.
Es wird nie gewartet, also nicht in `Queue.get()`. Und es wird immer `after()` aufgerufen. Es sei denn Du definierst irgendeinen Wert den der/die Threads an das Hauptprogramm/die GUI senden können/dürfen, der das Programm beenden soll.
Rekursion ist da übrigens keine. Die Methode ruft `after()` auf und kehrt zur Hauptschleife zurück. Das *die* dann später wieder die Methode aufruft ist keine Rekursion. Dafür müsste die Methode gleichzeitig mehrfach aktiv sein.
“Ich bin für die Todesstrafe. Wer schreckliche Dinge getan hat, muss eine angemessene Strafe bekommen. So lernt er seine Lektion für das nächste Mal.” — Britney Spears, Interview in der französischen Zeitung Libération, 2. April 2002
Habs jetzt mit einer 2.queue (Rückrichtung als Erledigungsmeldung) und ohne exit/quit (macht aus meiner sicht keinen Sinn,da die job-queue mehrmals gefüllt werden kann) gemacht.
def syncGUI(self):
while not self.doneq.empty():
item=self.doneq.get()
self.scrolltxt.insert(tk.END, str(item)+ '\n')
self.doneq.task_done()
if self.q.empty():
self.scrolltxt.insert(tk.END, 'no more jobs\n')
self.scrolltxt.see(tk.END)
self.win.after(200,self.syncGUI)
q ist die job-queue welche der thread abarbeitet,doneq ist die queue für die Rückmeldung.
Warum darf der thread die gui nicht direkt updaten? Hat auch funktioniert...könnte evtl. bei mehreren threads Probleme bereiten bei gleichzeitigem Zugriff.
Das hat funktioniert wie es auch funktioniert, mit geschlossenen Augen über die Straße zu gehen. Ohne vorher zu schauen, ob ein Auto kommt. Man stirbt nicht jedes Mal. Aber man *kann* sterben.
Die Innereien der GUI sind nicht davor geschützt, von mehreren Threads gleichzeitig bearbeitet zu werden. Dadurch können dann inkonsistente Zustände entstehen, die zu Abstürzen führen *können*. Nicht müssen. So wie man eben nicht zwangsläufig umkommt, wenn man ohne zu schauen auf die Straße rennt.
@frank-w: Ich würde das ohne `empty()` machen, mit einer ``while True:``-Schleife die dann verlassen wird wenn das `get_nowait()` eine Ausnahme auslöst weil die Queue tatsächlich leer ist.
Methodennamen übrigens klein_mit_unterstrichen.
“Ich bin für die Todesstrafe. Wer schreckliche Dinge getan hat, muss eine angemessene Strafe bekommen. So lernt er seine Lektion für das nächste Mal.” — Britney Spears, Interview in der französischen Zeitung Libération, 2. April 2002