Spazieren in der GUI

Fragen zu Tkinter.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Ach hab es doch gefunden:

Code: Alles auswählen

from tkinter import *

def doFoo(*args):
    print("Hello, world")

root = Tk()
root.bind("<<Foo>>", doFoo)

# some time later, inject the "<<Foo>>" virtual event at the
# tail of the event queue
root.event_generate("<<Foo>>", when="tail")
Quelle: http://stackoverflow.com/questions/2706 ... -main-loop

So etwas ist natürlich toll. Dann braucht doFoo in meinem Fall nur aufzurufen: send("voelligwurscht_aber_nicht_bereits_sonst_definiert") und die Abarbeitung läuft.

Noch eine Frage: wie ist das mit Python Threads. Kommt es zu einem Threadwechsel nur nach Ausführung vollständiger Python Befehle oder auch mittendrin?
Wenn ich etwa von einer anderen Task aus einen append mache, bevor in der Maintask ein pop kommt, ist kein Problem.
Wenn ich von einer anderen Task aus einen append mache, nachdem in der Maintask ein pop ausgeführt wurde, ist auch kein Problem.
Aber wenn ich einen append mache, während eines pops, das dürfte ein Problem sein, sofern man da nicht lockt. Also ist da ein lock erforderlich?

Oder anders ausgedrückt: laufen die Threadwechsel Pythongesteuert ab oder auf Prozessorebene?
BlackJack

@Alfons Mittelmeyer: Das mit dem Kontextwechsel bei Threads hatte ich gerade im dedizierten Thema dazu beantwortet, darum hier nur kurz: Es werden native Threads verwendet soweit auf dem System vorhanden, man muss also allgemein davon ausgehen das der Wechsel auf Prozessorebene stattfindet wenn man threadsicher programmieren will. `Queue.Queue` aus der Standardbibliothek ist aber beispielsweise von der Dokumentation her garantiert threadsicher und `collections.deque` auch. So etwas muss man sich also nicht aus einer Liste und Sperrobjekten selber basteln.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@Alfons Mittelmeyer: Das mit dem Kontextwechsel bei Threads hatte ich gerade im dedizierten Thema dazu beantwortet, darum hier nur kurz: Es werden native Threads verwendet soweit auf dem System vorhanden, man muss also allgemein davon ausgehen das der Wechsel auf Prozessorebene stattfindet wenn man threadsicher programmieren will. `Queue.Queue` aus der Standardbibliothek ist aber beispielsweise von der Dokumentation her garantiert threadsicher und `collections.deque` auch. So etwas muss man sich also nicht aus einer Liste und Sperrobjekten selber basteln.
Hatte im anderen Thread jetzt auch dazu geschrieben warum es so gemacht wird. Denn durch ein atomares Objekt, wie Fileschreiben, das länger dauert, käme der andere Thread ansonsten in der Zwischenzeit nicht dran.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@Alfons Mittelmeyer: Das mit dem Kontextwechsel bei Threads hatte ich gerade im dedizierten Thema dazu beantwortet, darum hier nur kurz: Es werden native Threads verwendet soweit auf dem System vorhanden, man muss also allgemein davon ausgehen das der Wechsel auf Prozessorebene stattfindet wenn man threadsicher programmieren will. `Queue.Queue` aus der Standardbibliothek ist aber beispielsweise von der Dokumentation her garantiert threadsicher und `collections.deque` auch. So etwas muss man sich also nicht aus einer Liste und Sperrobjekten selber basteln.
Also hab es mal mit queue (Python3) gemacht. Hier das Modul execute_gui.py:

Code: Alles auswählen

from spazieren import *
import queue

_queue = queue.Queue()
_root = None

def _execute(*args):
    try:   _queue.get()()
    except: print("execute error")
	
def init(root):
    global _root
    _root = root
    root.bind("<<EXEC>>",_execute)

def execute(command): 
    _queue.put(command)
    _root.event_generate("<<EXEC>>", when="tail")
Und dazu das angepasste buttons.py:

Code: Alles auswählen

from spazieren import *
import execute_gui
import threading

class App:
  def __init__(self, master):
    frame = Frame(master)
    frame.pack()
    self.button = Button(frame, 
                         text="QUIT", fg="red",
                         command=frame.quit)
    self.button.pack(side=LEFT)
    self.slogan = Button(frame,
                         text="Hello",
                         command=self.write_slogan)
    self.slogan.pack(side=LEFT)
  def write_slogan(self):
    print("Tkinter is easy to use!")

root = Tk()
app = App(root)
ls()

execute_gui.init(root)

class MyThread(threading.Thread):
    def run(self):
        while True:
            a = input("> ")
            try: 
                command = lambda cmd=compile(a+"\nls()",'<string>', 'exec'): eval(cmd)
                execute_gui.execute(command)
            except: print("Error:",a)
 
mythread = MyThread()
mythread.daemon = True
mythread.start()

root.mainloop()
Hoffe, dass das jetzt auch unter Windows geht.

Außerdem hattest Du geschrieben:
BlackJack hat geschrieben:@Alfons Mittelmeyer: Events sind auch thread-safe, allerdings benutzt das kaum jemand weil die Implementierung in der `Tkinter`-Anbindung nicht vollständig ist. Man kann nur Ereignisse ohne zusätzlich Daten auslösen, also wirklich nur ein Event mit einem eigenen Namen ohne das man da weitere Informationen mitgeben kann. Wenn einem das reicht, kann man das natürlich so verwenden. In der Praxis habe ich das aber nur *sehr* selten gesehen, in der Regel wird einem immer eine `Queue.Queue` und `after()`/`after_idle()` nahegelegt.
Stimmt natürlich nicht ganz, denn den command kann man auch mit Parametern machen. Sozusagen Funktionsaufruf von außen in Gui Callback verwandelt.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:In der Praxis habe ich das aber nur *sehr* selten gesehen, in der Regel wird einem immer eine `Queue.Queue` und `after()`/`after_idle()` nahegelegt.
Tut mir leid BlackJack, wenn man jetzt die gängige Praxis und die Empfehlungen wohl ändern müssen wird.
BlackJack

@Alfons Mittelmeyer: Bei Tk kann man dem Ereignis auch Daten mitgeben, bei `Tkinter` geht das nicht, weil der nötige Code bei der Anbindung fehlt.

Und bezüglich des letzten Beitrags: Könntest Du bitte dieses Trollen unterlassen. Danke.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@Alfons Mittelmeyer: Bei Tk kann man dem Ereignis auch Daten mitgeben, bei `Tkinter` geht das nicht, weil der nötige Code bei der Anbindung fehlt.

Und bezüglich des letzten Beitrags: Könntest Du bitte dieses Trollen unterlassen. Danke.
Ja BlackJack, Du hast mir heute weitergeholfen, sodass ich die Lösung finden konnte. Aber Du weisst auch, was sich die Tage zuvor hier in diesem Forum abgespielt hatte. Weißt Du, ich bin kein Mensch der andere angreift. Mir liegt daran, dass man sich gegenseitig hilft und gemeinsam nach Lösungen sucht. Aber dafür, dass Moderatoren verbal auf User einprügeln, wie es die letzten Tage geschah, habe ich nicht viel Verständnis. Wenn Du bereit bist, Dein Verhalten mir gegenüber zu ändern, bin ich gerne bereit dasselbe zu tun. Also, wie ist es?
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@BlackJack Ich verstehe auch nicht, wie man zur Auffassung gelangt, dass dieser Event nicht viel nützt, weil er keinen zusätzlichen Parameter hat. Und dann empfiehlt man die Verwendung einer Queue in Verbindung mit after. Nur ist es so, mit zusätzlichem Parameter könnte man Funktionen mit Parametern in einem Tuple direkt aufrufen und bräuchte dann keine Queue. Wenn man aber eine Queue nimmt, braucht mein keinen zusätzlichen Parameter.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Das nutzliche an Queue ist die threadsicherheit.

Bzw. Könnte man nicht in der queue eine Nachricht hinterlegen, den event auslösen und dann dort nachsehen?!?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

jens hat geschrieben:Das nutzliche an Queue ist die threadsicherheit.

Bzw. Könnte man nicht in der queue eine Nachricht hinterlegen, den event auslösen und dann dort nachsehen?!?
Also in welcher Form Du etwas in der Queue hinterlegst, bleibt Dir überlassen. Man könnte etwa auch (function,(par1,par2,par2)) ablegen und dann function(*args) aufrufen. Da kannst Du alles machen, was Du dir vorstellst.

Eine Queue ist auch nicht etwas viel anderes wie eine Liste. Man hätte auch eine Liste nehmen können mit append und pop(0). Allerding für Threadsicherheit wäre dann noch Lock.acquire() und Lock.release() je zweimal mt try und finally erforderlich gewesen. Bei der Queue ist das schon eingebaut und so sieht der Code dann einfacher und klarer aus.

Also, ich bin ein paar Tage nicht da, nicht wundern, wenn ich mich nicht rühre.
BlackJack

@Alfons Mittelmeyer: Gegenseitig helfen und nach Lösungen suchen geht in Ordnung. Wenn die Hilfe aber nicht angenommen wird, Fakten ignoriert werden, Falschaussagen hartnäckig wiederholt werden, und alle von dem einen der's nicht einsehen will dann verbal angepinkelt werden, dann verhalte ich mich entsprechend so wie ich mich verhalten habe und verhalten werde wenn das wieder passiert/so weiter geht. Wie man in den Wald hinein ruft…

Eine Liste als Queue zu verwenden mit `append()` und ``pop(0)`` ist keine gute Idee weil das ``pop(0)`` ineffizient ist — da müssen dann jedesmal alle folgenden Elemente um eine Position nach vorne kopiert werden. Die `Queue` dagegen ist so implementiert das beide Operationen konstante Zeit benötigen, unabhängig von der Anzahl der Elemente in der `Queue`.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@Alfons Mittelmeyer: Gegenseitig helfen und nach Lösungen suchen geht in Ordnung. Wenn die Hilfe aber nicht angenommen wird, Fakten ignoriert werden, Falschaussagen hartnäckig wiederholt werden, und alle von dem einen der's nicht einsehen will dann verbal angepinkelt werden, dann verhalte ich mich entsprechend so wie ich mich verhalten habe und verhalten werde wenn das wieder passiert/so weiter geht. Wie man in den Wald hinein ruft…
Hi Blackjack, was soll man dazu sagen, wie Du auf mein faires Angebot eingehst. Was soll man dazu sagen, wie Du die Zeit meiner Abwesenheit nutzt. Was soll man dazu sagen, wie Du jetzt sogar noch ins fäkalische abgleitest. Ich würde sagen, denke noch einmal gründlich aber sehr gründlich darüber nach, besonders über das fett hervorgehobene, ob Du nicht besser etwas davon zurücknehmen willst. Morgen abends kann ich ja einmal nachsehen, ob Du etwas nachgedacht hast.
BlackJack

@Alfons Mittelmeyer: Was soll man dazu sagen das Du Fragen nicht mit einem Fragezeichen enden lässt? Da habe ich jetzt echt gründlich drüber nachgedacht. ;-)

Und nein, ich möchte nichts davon zurücknehmen. Warum sollte ich denn etwas davon zurücknehmen? Du kannst Dich nicht so aufführen und dann erwarten dass das keine Auswirkungen auf den Ton der Konversation hat. Wenn man Leute fortgesetzt nervt, reagieren sie halt irgendwann gereizt.
Benutzeravatar
snafu
User
Beiträge: 6745
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@BlackJack: Nun lass dich mal nicht persönlich provozieren. Dann hilfst du ihm in Zukunft eben nicht mehr. Du siehst ja wie dieser Mensch damit umgeht. Manche Leute stellen sich eben wahnsinnig gerne als arme Opfer dar und würden niemals einsehen wollen, dass sie mit ihrer Einschätzung einfach mal daneben lagen.

Wir sind vernünftige Menschen und können, falls notwendig, auch einander aus dem Weg gehen, finde ich. Ich glaube, du hast es nicht nötig, dich in Streitereien verstricken zu lassen, die allmählich den Charakter einer Seifenoper annehmen... ;)
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@Alfons Mittelmeyer: Was soll man dazu sagen das Du Fragen nicht mit einem Fragezeichen enden lässt? Da habe ich jetzt echt gründlich drüber nachgedacht. ;-)

Und nein, ich möchte nichts davon zurücknehmen. Warum sollte ich denn etwas davon zurücknehmen? Du kannst Dich nicht so aufführen und dann erwarten dass das keine Auswirkungen auf den Ton der Konversation hat. Wenn man Leute fortgesetzt nervt, reagieren sie halt irgendwann gereizt.
Da ist es ja schon wieder, nämlich die Unterstellung, dass ich mich in irgendeiner Weise ungebührlich aufgeführt hätte. Außerdem nimmst Du von dem, was Du behauptest hattest - und das war ja ein Hammer - auch nichts zurück. Es ist klar, dass man das nicht so stehen lassen kann. Und dass man das ein für alle mal aus der Welt schaffen muss. Daher werde ich Dir morgen einen Vorschlag unterbreiten, wie ich mir vorstelle, dass man das handhaben könnte. Du kannst dann den Vorschlag annehmen, oder, falls er Dir nicht behagt, mir einen Gegenvorschlag unterbreiten.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

:roll:

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@Alfons Mittelmeyer: Was soll man dazu sagen das Du Fragen nicht mit einem Fragezeichen enden lässt? Da habe ich jetzt echt gründlich drüber nachgedacht. ;-)

Und nein, ich möchte nichts davon zurücknehmen. Warum sollte ich denn etwas davon zurücknehmen? Du kannst Dich nicht so aufführen und dann erwarten dass das keine Auswirkungen auf den Ton der Konversation hat. Wenn man Leute fortgesetzt nervt, reagieren sie halt irgendwann gereizt.
Vielleicht war ja unser Disput zu theoretisch und abstrakt für Dich. Machen wir es doch einfach so: ich erstelle ein kleines leicht begreifbares Beispiel und dann schreibst Du dazu Deine Meinung. Was hältst Du davon? Und da es nicht speziell tkinter ist, gehört es wohl in das Forum Allgemeine Fragen.
BlackJack

@Alfons Mittelmeyer: Genau ich bin zu dumm, schreib also etwas wirklich praktisches und konkretes, damit ich das auch wirklich begreife… :roll:

Davon halte ich gar nichts, weil ich nicht sehe welches Problem das jetzt lösen soll. Wenn jemand einen Beitrag mit einem Beispiel schreibt, mit der Frage „Was haltet ihr davon?” dann antworte ich darauf, oder halt auch nicht. Und zwar völlig unabhängig von unserem ”Disput”.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@Alfons Mittelmeyer: Genau ich bin zu dumm, schreib also etwas wirklich praktisches und konkretes, damit ich das auch wirklich begreife… :roll:

Davon halte ich gar nichts, weil ich nicht sehe welches Problem das jetzt lösen soll. Wenn jemand einen Beitrag mit einem Beispiel schreibt, mit der Frage „Was haltet ihr davon?” dann antworte ich darauf, oder halt auch nicht. Und zwar völlig unabhängig von unserem ”Disput”.
Ein einfaches konkretes praktisches Beispiel hätte ich. Das ist auch nötig, dann sachlich Unrichtiges kann man so nicht stehen lassen. Allerdings, bevor man wieder sachlich miteinander diskutieren kann, müssen sich erst erhitzte Gemüter etwas abkühlen. Und auch ich bin mir nicht sicher ob ich zur Zeit nach diesem sehr erhitzten Disput jegliche Stichelei - normalerweise tue ich so etwas nicht - unterlassen würde. Also ein wenig wird man wohl noch abwarten müssen, bevor man wieder neu anfängt, und zwar diesmal sachlich.
Benutzeravatar
sparrow
User
Beiträge: 4202
Registriert: Freitag 17. April 2009, 10:28

Ich spende 5 Euro an die EFF, wenn jemand diesen Thread, der bei mir den Eindruck einer gewissen Warhnehmungsproblematik fördert, schließt.
Gesperrt