Gui-Anderung einer Eigenschaft in einem anderen Modul

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

@BlackJack War mir nicht sicher, ob das mit target geht, weil ich es selber noch nicht ausprobiert hatte und dazu nur dieses Beispiel gefunden hatte:

Code: Alles auswählen

t = threading.Thread(target=worker, args=(i,))
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Und zweiseitige Kommunikation zwischen GUI und Thread ist auch möglich, denn der Thread, kann der GUI mitteilen, welche Antwortfunktion sie aufrufen soll. Der Thread könnte etwa in ein event.wait() gehen und die Antwortfunktion schreibt etwas in eine Queue und setzt dann event.set()

Also Funktionen im Thread können von der GUI etwas abragen und das als Rückgabewerte zur weiteren Verarbeitung liefern. Auch interessant, oder? In so einem Fall reicht aber wohl auch eine Variable statt eine Queue.
Sirius3
User
Beiträge: 18266
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: oder eine Queue statt eines Events und einer Variable. Natürlich ist der bessere Weg, die Argumente einer worker-Funktion als args unzugeben, statt da nochmal extra eine lambda-Expression zu schreiben, denn dazu ist ja das args-Argument da.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@Sirius3 Ja stimmt, man muss es ja nicht über das Message System machen, sondern kann Threads auch direkt starten. Es sei denn, es ist nicht festgelegt, dass man das über Threads macht, sondern nur dass man es über eine bestimmte Message tut. In diesem Fall macht man es direkt über die Argumente, weil ja kein Objekt bekannt sein muß, das sich irgendwo befinden kann, sondern einen neuen Thread kann man jederzeit starten.

Das mit dem Senden macht man, wenn man nicht weiß, wo etwas ist. Es kann auch sein, dass nur mehr Callbacks mit ihren Parametern existieren, die nur an das Message System gebunden sind und sonst keinerlei Referenz mehr haben. So mache ich es etwa.

Ich habe also nur Widgets und an die Widgets oder das Messagesystem gebundene Callbacks. Sonst exisiert nichts mehr von meinem Programm, wenn es ausgeführt wird - außer natürlich meiner Library für die Widgets, das Messagesystem und damit in Beziehung stehende Funktionen.

Dann ist natürlich interessant, dass man die Geschäftslogik auch sequentiell in einem Thread schreiben kann. Eine Funktion etwa im Thread öffnet in der GUI eine Eingabemaske und wartet bis die Eingabe abgeschlossen ist. Als Rückgabewert liefert sie dann zurück, ob die Eingabe gemacht wurde und dann mit den Daten, oder ob sie abgebrochen wurde.

Dann ist man völlig unabhängig von jeder GUI Logik und kann seine Anwendung sequentiell mit Interface Funktionen für Eingabemasken schreiben, ob die jetzt über tkinter GUI definiert sind oder sonstwie.

Und da ist der Vorteil meines Systems, wenn man solche Eingabemasken schließt, dann kann man das so machen, das sie restlos weg sind. Und man kann diese und andere wieder jederzeit nachladen - mit dazugehörigen Interface Funktionen.

Wie das dann aussehen kann: eine Funktion des Threads sendet, welche Eingabemaske es sein soll. Danach sendet sie, welche Anwortfunktion aufzurufen ist, dann wartet sie, bis diese aufgerufen wird, holt sich die Daten und kehrt mit 'return data' zurück. Völlig unabhängig davon, wie die GUI implementiert ist.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Idee für Geschäftslogik in einem Thread:

Code: Alles auswählen

import threading
import messaging

class MyApp(threading.Thread):
   
    def __init__ (self):
        self.data = None
        self.event = threading.Event()
        threading.Thread.__init__ (self)

    def return_data(self,data):
        self.data = data
        self.event.set()

    def get_user_data(input_mask,fill_data=None):
        self.event.clear()
        messaging.send('LOAD_MASK',input_mask) # implemented in the GUI for such applications - a simple implementation: destroy current content of the root window and load the root window from file
        if fill_data != None: messaging.send('FILL_MASK',fill_data) # input mask specific
        messaging.send('RETURN_DATA',self.return_data) # where to store this is input mask specific
        self.event.wait()
        return self.data


    def run(self):

        address = get_user_data('address_mask')
        # and so on
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Lösung für Geschäftslogik in anderem Thread eventgesteuert.

Der Logikthread hat den Vorteil auch längere Aktionen durchführen zu können, ohne die GUI zu blockieren.
Dieser Thread ist Message Event gesteuert mit einer Loop über die Queue. Wenn sie leer ist, wartet der Thread auf ein event.

Wie kann dieser Thread sich in das GUI Message System ohne großen Aufwand reinhängen, sodaß die GUI auch an ihn Messages senden kann.
In der Queue der GUI wurden diese Daten abgelegt:

Code: Alles auswählen

self.Queue.put((msgid,msgdata))
An die Callbacks wurden allerdings nur die msgdata gesendet.

Gut wäre es, für einen andern Thread immer dieselbe Callback Funktion zur Verknüpfung dar zwei Messagesysteme zu haben. Dazu führen wir ein packed Flag im Messagesystem ein. So wurde bisher gesendet:

Code: Alles auswählen

            if msgid in self.Dictionary:
                receivers = self.Dictionary[msgid].items()
                for receive,active in receivers:
                    if active: receive(msgdata)
Das active unterteilen wir jetzt in eine Liste mit zwei Elementen. active[0] ist das frühere active Flag, active[1] das neue packed Flag:

Code: Alles auswählen

for receive,active in receivers:
    if active[0]:
        if active[1]: receive((msgid,msgdata))
        else receive(msgdata)
Diese Änderung müssen wir dann hier nachziehen:

Code: Alles auswählen

    def _register(self,msgid,receive,packed=False):
        if msgid not in self.Dictionary: self.Dictionary[msgid] = {}
        self.Dictionary[msgid][receive] = [True,packed]

    def do_receive(self,owner,msgid,receive,packed=False):
        if not owner in self.owners: self.owners[owner] = {}
        self.owners[owner][receive]=msgid
        self.execute_lambda(lambda: self._register(msgid,receive,packed))

    def activate_receive(self,msgid,receive,flag):
        if msgid in self.Dictionary:
            receivers = self.Dictionary[msgid]
            if receive in receivers:
                receivers[receive][0] = flag
Sowie auch hier:

Code: Alles auswählen

    def _sendImmediate(self,msgid,msgdata=None):
        while True:
            if msgid in self.Dictionary:
                receivers = self.Dictionary[msgid].items()
                self.counter += 1
                for receive,active in receivers:
                    if active[0]:
                        if active[1]: receive((msgid,msgdata))
                        else receive(msgdata)
                self.counter -= 1

            if self.counter > 0: return
            if self.Queue.empty(): return
            data = self.Queue.get()                
            msgid = data[0]
            msgdata = data[1]

    def _send(self,*args):
        try:
            data = self.Queue.get()
            msgid = data[0]
            msgdata = data[1]
            if msgid in self.Dictionary:
                receivers = self.Dictionary[msgid].items()
                for receive,active in receivers:
                    if active[0]:
                        if active[1]: receive((msgid,msgdata))
                        else receive(msgdata)
        except: print("sendQeue error")
Mit do_receive und dem packed flag, kann der andere Thread dann immer dieselbe Callbackfunktion für alle Messages beim GUI Messagesystem registrieren:

Code: Alles auswählen

def receive_packed(self,message):
	self.Queue.put(message)
	self.event.set()
Diese message enthält nämlich bereits das tuple mit den zwei Teilen (msgid,msgdata). Ist klar dass der Thread dann für seine eigenen Messages und die, welche er von der GUI bekommt, auch bei sich eigene Callbacks implementieren sollte.

Und wenn wir dann für die GUI vor mainloop() Start auch diese message event gesteuerte Loop implementieren, wäre das System auch vorher bereits threadsicher. Danach müssen wir aber aus dieser Loop herausgehen. Und mit dieser Funktion und dem packed Flag können dann verschiedene Treads gegenseitig Message Callbacks implementieren, wie sie nur wollen:

Code: Alles auswählen

def receive_packed(message):
    self.Queue.put(message)
    self.event.set()
Allerdings für die GUI ist dies für nach mainloop start noch geringfügig zu ändern:

Code: Alles auswählen

def receive_packed(message):
    self.Queue.put(message)
    if _mainloop_started: self.app.event_generate("<<SEND>>", when="tail")
    else: self.event.set()
Damit hätten wir dann eine multiple Thread message gesteuerte Interkommunikation.

Wenn die Threads bei sich gegenseitig Callbacks installieren, brauchen die Sender gar nicht mehr zu wissen, was sie an welche Threads senden müssen.

Jetzt kann man sich überlegen, welcher Thread was macht. Oder ob einer viel macht und den Rest weiterleitet. Oder ob man gleich einen Message Router dazwischen schaltet, bei dem man nur mehr konfiguriert, welcher Thread für was zuständig ist.

Ein Message Router würde einfach in einem Dictionary nachsehen, welche Message er an welche Threads weiterleiten soll, oder über welche Bussysteme oder über welche URLs oder über welche Server, oder über welche Protokolle.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Habe mir noch überlegt, wie das aussehen könnte mit einem Messaging System über mehrere Threads verteilt.
Dazu braucht man einen zentralen Thread, den jeder kennen muss. Die anderen Threads braucht man nicht zu kennen.
Die anderen Threads registrieren da ihre Callbacks und senden alles, was nach außen gehen soll, dorthin.
Wir brauchen aber noch eine zweite Queue, nämlich eine High Priority Queue, damit keine Message an einen Empfänger geschickt wird, der nicht mehr existiert.
Und dann brauchen wir noch eine Funktion, um eine Loop im Proxy zu starten:

Code: Alles auswählen

import threading
import proxy

class Register_Callbacks(threading.Thread)

    def __init__ (self, execute_lambda):
        self.proxy = proxy.MessageProxy()
        threading.Thread.__init__ (self)

    def send(self,msgid,message=None): self.proxy.send(msgid,message)
    def do_receive(self,owner,msgid,receive,packed=False): self.proxy.execute_lambda_highprio(lambda ow=owner,mid=msgid,rec=receive,pack=packed:self.proxy.do_receive(ow,mid,rec,pack))
    def undo_receiveAll(self,owner): self.proxy.execute_lambda_highprio(lambda ow=owner:self.proxy.undo_receiveAll(ow))

    def run(self): self.proxy.loop()

central_callbacks = Register_Callbacks()
central_callbacks.start()
Die Funktionsaufrufe muss man eventuell noch threadsicher umformulieren

Threadsicherheit auch schon vor mainloop Start. Messages von extern schreiben in die Queue triggern aber nichts:

Code: Alles auswählen

def receive_packed(message):
    self.Queue.put(message)
    if _mainloop_started: self.app.event_generate("<<SEND>>", when="tail")
Das wird dann vom send handling vor der loop sporadisch mit abgeholt oder spätestens bei loop start
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

snafu hat geschrieben:
BlackJack hat geschrieben:@snafu: `Tkinter`\s benutzerdefinierte Ereignisse haben allerdings den Nachteil das man keine Daten damit übermitteln kann.
Das hatte ich wohl verdrängt. Wäre ja zu schön, wenn TKinter in Python ein vollwertiges Event-System hätte...
Gibt es kein Zusatzpaket, welches genau das macht?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

@jens: Speziell für Tkinter? Da wäre es wohl sinnvoller Tkinter zu fixen denn Tk an sich kann das ja. Das das in den ganzen Jahr*zehnten* niemand gemacht hat, zeigt IMHO den Bedarf dafür: gleich Null.

Allgemein gibt's einen ganzen Haufen von Publisher/Subscriber-Nachrichtensystemen. Schrieb ich ja schon mal. Wenn die Anwendung eine Komplexität erreicht hat das man diese Art von Entkopplung tatsächlich *braucht* dann will man aber in der Regel auch nicht Tk dafür verwenden. Und die anderen, moderneren GUI-Toolkits bringen Events *mit* Daten ja von Haus aus schon mit.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ja, komisch. Ich gehe dann mal davon aus, das es nicht mal so einfach zu Implementieren ist. Ansonsten hätte es ja sicherlich jemand gemacht. Wenn es Tk eh schon kann.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

@jens: Das wird bestimmt nicht schön, denn Tk ist ja eine „stringly typed“ Programmiersprache, also im Grunde kennt die nur Zeichenketten als Datentyp. Man müsste sich also die tatsächlichen Werte irgendwo merken, zum Beispiel ein Wörterbuch das generierte IDs auf die Objekte abbildet und dann als Daten beim Event eine Zeichenkette mit den IDs senden. Und für den Empfänger kann man die dann parsen und sich die tatsächlichen Werte aus dem Wörterbuch holen. Dann fangen aber auch schon ähnliche Probleme wie bei Bildern in Tk an: Solange die Zeichenkette mit den IDs innerhalb von Tk irgendwo unterwegs ist, muss man Referenzen auf die Werte behalten, andererseits will man die nicht für alle Ewigkeit aufheben. Das macht alles mehr Probleme als es Nutzen bringt IMHO. Und anscheinend nicht nur IMHO. :-)
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@jens Ich weiss nicht, was Du hast. Nocht nicht kapiert, dass man keinen zusätzlichen Parameter für einen generierten Event braucht, wenn man eine Queue nimmt.

Jetzt kommt es aber dicke. Ich habe das Messaging System nun implementiert, welches erlaubt, dass beliebige viele Tasks miteinander Nachrichten austauschen.
Und sie brauchen sich auch nicht gegenseitig zu kennen, weil der Nachrichtenaustausch über einen Proxy geht, der allen bekannt ist.

Hier ein Bespiel mit drei Tasks, die über einen vierten miteinander kommunizieren.

Erster Task, der Fragesteller frage.py. Der Benutzer tippt etwas ein in die Konsole, etwa eine Frage. Das schickt diese Task an den extern_proxy weiter.

frage.py:

Code: Alles auswählen

import threading
import extern_proxy

class MyThread(threading.Thread):

    def run(self):
        while True:
            frage = input("> ")
            extern_proxy.proxy.send("FRAGE",frage)
 
mythread = MyThread()
mythread.daemon = True
mythread.start()
Der Letze in der Reihe bekommt die frage und die Antwort und gibt sie in der Konsole aus.

frage_antwort.py:

Code: Alles auswählen

import threading
import extern_proxy
import proxy

class MyThread(threading.Thread):

    def run(self):
        self.proxy = proxy.Proxy(extern_proxy.proxy)
        self.proxy.do_receive(self,"FRAGE_ANTWORT",lambda msg: print("Frage:",msg[0],"- Antwort:",msg[1]))
        self.proxy.do_receive_extern(("FRAGE_ANTWORT",))
        self.proxy.loop()
 
mythread = MyThread()
mythread.daemon = True
mythread.start()
Um Nachrichten auszutauschen, wird ein Proxy eingerichtet. Damit Nachrichtentausch auch mit dem externen Proxy möglich ist, wird dieser dem eigenen Proxy bekanntgegeben:

Code: Alles auswählen

self.proxy = proxy.Proxy(extern_proxy.proxy)
Dann wird eine Callback Funktion für die Message "FRAGE_ANTWORT" eingerichtet, welche dann das Ergebnis ausgibt:

Code: Alles auswählen

self.proxy.do_receive(self,"FRAGE_ANTWORT",lambda msg: print("Frage:",msg[0],"- Antwort:",msg[1]))
Woher soll diese Message kommen? Von hier nicht, sondern vom externen Proxya. Dem gibt man eine Liste bekannt. Aber hier nur ein Element:

Code: Alles auswählen

self.proxy.do_receive_extern(("FRAGE_ANTWORT",))
Irgendwer muss ja die Frage beantworten. Das macht dann eine tkinter GUI Anwendung.

antwort.py:

Code: Alles auswählen

import frage
import frage_antwort

import extern_proxy
import proxy as myproxy
import tkinter as tk

proxy = myproxy.Proxy(extern_proxy.proxy)

# external message callbacks
proxy.do_receive_extern(("FRAGE",))
proxy.do_send_extern(("FRAGE_ANTWORT",))

root = tk.Tk()

frage = tk.Label()
frage.pack()

antwort = tk.Entry()
antwort.pack()

def get_frage(msg):
    frage['text'] = msg
    antwort.delete(0,'end')

# internal callbacks
proxy.do_receive(root,"FRAGE",get_frage)
antwort.bind("<Return>",lambda event: proxy.send('FRAGE_ANTWORT',(frage['text'],antwort.get())))

# tk trigger for proxy
root.bind("<<SEND>>",proxy.work)
proxy.set_trigger(lambda: root.event_generate("<<SEND>>", when="tail"))

root.mainloop()
Hier auch wieder der Proxy, der den externen kennt. Dem gibt man bekannt, dass man "FRAGE" von extern empfangen will und FRAGE_ANTWORT nach außen weiterleiten will:

Code: Alles auswählen

proxy.do_receive_extern(("FRAGE",))
proxy.do_send_extern(("FRAGE_ANTWORT",))
Die Callbackfunktionen sind ganz normal wie bei internem Senden und Empfangen (es wird nur weitergeletet durch die Definitionen vorher):

Code: Alles auswählen

proxy.do_receive(root,"FRAGE",get_frage)
antwort.bind("<Return>",lambda event: proxy.send('FRAGE_ANTWORT',(frage['text'],antwort.get())))
In die normale threading Event Loop darf man den Proxy nicht schicken, daher setzt man die tk GUI Trigger für ihn:

Code: Alles auswählen

# tk trigger fror proxy
root.bind("<<SEND>>",proxy.work)
proxy.set_trigger(lambda: root.event_generate("<<SEND>>", when="tail"))
Und diese Kommunikation erfolgt über eine vierte Task, welche die Verbindung zwischen den anderen Tasks herstellt. Da seid Ihr sicher gespannt, wie dieses Wunderding aussieht, oder?

extern_proxy.py:

Code: Alles auswählen

import threading
import proxy as myproxy

proxy = None

class MyThread(threading.Thread):
 
    def run(self):
        global proxy
        self.proxy = myproxy.Proxy()
        proxy=self.proxy
        self.proxy.loop()

mythread = MyThread()
mythread.daemon = True
mythread.start()
Es ist einfach nur ein Thread mit einem Proxy in der Loop. Die anderen Threads geben diesem Proxy einfach nur bekant, welche Nachrichten sie haben wollen. Und wenn Nachrichten zu diesm Proxy geschickt werden, sendet er sie an die Empfängerproxys weiter.

Die Logik findet sich im Proxy.

proxy.py:

Code: Alles auswählen

import queue
import threading 
 
 
class Proxy:
 
    def __init__(self,extern_proxy=None):
        if extern_proxy == None: self.extern_proxy = self
        else: self.extern_proxy = extern_proxy
        self.reset()

    def noop(self): pass


    def reset(self):
        self.Dictionary = {}
        self.owners = {}
        self.Queue = queue.Queue()
        self.Queue_HighPrio = queue.Queue()
        self._register("execute_function",lambda msg: msg())
        self.running = False
        self.trigger = self.do_work
        self.extern_trigger = self.noop

    def set_trigger(self,trigger):
        self.trigger = trigger
        self.extern_trigger = trigger

    def do_work(self):
        if self.running: return
        self.running = True
        while self.work(): pass
        self.running = False

    def loop(self):
        self.event = threading.Event()
        self.set_trigger(self.event.set)
        self.trigger()
        while True:
            self.event.wait()
            while self.work(): pass

    def work(self,*args):
        if not self.Queue_HighPrio.empty(): data = self.Queue_HighPrio.get()
        elif not self.Queue.empty(): data = self.Queue.get()
        else: return False

        msgid = data[0]
        msgdata = data[1]
        if msgid in self.Dictionary:
            receivers = self.Dictionary[msgid].items()
            for receive,packed in receivers:
                if packed: receive((msgid,msgdata))
                else: receive(msgdata)
        return True

    # sending ==========================================================

    def send(self,msgid,msgdata=None):
        self.Queue.put((msgid,msgdata))
        self.trigger()

    # extern send and receive callbacks ==========================================

    def do_send_extern(self,message_ids):
        for mid in message_ids: self.do_receive(self,mid,self.send_extern,True)

    def send_extern(self,message): self.extern_proxy.send(message[0],message[1])

    def do_receive_extern(self,message_ids):
        for mid in message_ids: self.extern_proxy.do_receive(self,mid,self.receive_extern,True)

    def receive_extern(self,message):
        self.Queue.put(message)
        self.extern_trigger()

    # register receiver ================================================

    def do_receive(self,owner,msgid,receive,packed=False):
        self.Queue_HighPrio.put(("execute_function",lambda: self._do_receive(owner,msgid,receive,packed)))
        self.trigger()

    def _do_receive(self,owner,msgid,receive,packed):
        if not owner in self.owners: self.owners[owner] = {}
        self.owners[owner][receive]=msgid
        self._register(msgid,receive,packed)

    def _register(self,msgid,receive,packed=False):
        if msgid not in self.Dictionary: self.Dictionary[msgid] = {}
        self.Dictionary[msgid][receive] = packed

    # unregister receiver ================================================

    def undo_receive(self,owner,msgid,receive):
        self.Queue_HighPrio.put(("execute_function",lambda: self._undo_receive(owner,msgid,receive)))
        self.trigger()
 
    def _undo_receive(self,owner,msgid,receive):
        if owner in self.owners:
            if receive in self.owners[owner]: del self.owners[owner][receive]
        self._unregister1(msgid,receive)

    def _unregister1(self,msgid,receive):
        if msgid in self.Dictionary:
            receivers = self.Dictionary[msgid]
            if receive in receivers:
                del receivers[receive]
                if len(receivers) == 0: del self.Dictionary[msgid]

    # unregister Owner ================================================

    def undo_receiveAll(self,owner):
        self.Queue_HighPrio.put(("execute_function",lambda: self._undo_receiveAll(owner)))
        self.trigger()

    def _undo_receiveAll(self,owner):
        if owner in self.owners:
            messages = self.owners[owner]
            del self.owners[owner]
            for receive,msgid in messages.items(): self._unregister1(msgid,receive)
Konnte keine Ruhe finden. Musste es einfach machen.
Zuletzt geändert von Alfons Mittelmeyer am Mittwoch 2. September 2015, 13:53, insgesamt 1-mal geändert.
Benutzeravatar
sparrow
User
Beiträge: 4536
Registriert: Freitag 17. April 2009, 10:28

Wenn man den Aufstand bei Tk machen muss, und das hinterher auch noch hässlich ist, bleibe ich lieber bei Qt ;)
BlackJack

@sparrow: Oder man bindet etwas bereits existierendes ein das es schon etwas länger gibt und das nicht von jemandem mit nur zwei Monaten Python-Erfahrung und interessanten Ansichten was ”übersichtlich” ist, programmiert wurde. wxPython hat zum Beispiel ein `pubsub`-Modul was es auch separat zum installieren gibt.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Irgendwo scheint Ihr wohl nichts zu kapieren. Es geht nicht darum, dass man dieses Beispiel FRAGE ANTWORT auch schöner programmieren kann. Es ging darum aufzuzeigen, dass beliebig viele Tasks miteinander kommunizieren können. Da könnte man sogar ein ganzes Netzwerk von Tasks errichten. Und es ist ganz normal, dass jeder Task eine Message Liste hat, was nach außen gehen soll, und was von außen reinkommen soll.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Alfons Mittelmeyer hat geschrieben:Irgendwo scheint Ihr wohl nichts zu kapieren.
Das ist nur allzu menschlich. Jeder von uns hat blinde Flecke mit nahezu null Ahnung. Das ist nicht schlimm. Viel gefährlicher ist Halbwissen. Es verleitet uns immer wieder, Dinge zu behaupten und zu tun, wo sich der gesunde Menschverstand an den Kopf fassen möchte.
BlackJack

@Alfons Mittelmeyer: Wenn ich beliebig viele Tasks miteinander kommunizieren lassen möchte dann nehme ich trotzdem nichts was von einem Anfänger zusammengebastelt wurde, sondern etwas das sich schon in der Praxis bewährt hat. Also zum Beispiel das `pubsub`-Modul von wxPython oder ØMQ oder RabbitMQ wenn das ganze auch richtig fett skalieren können soll. :-)
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Hat jemand eine Ahnung, wie man mehrere offene Python Anwendungen miteinander kommunziern läßt?
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@BlackJack Natürlich kannst Du mit Kanonen auf Spatzen schießen, wenn Du ein klein wenig Interkommunikation brauchst. Vielleicht schon überlegt, dass man auf Buttondruck den zugehörigen Callback ja auch über TCPIP aufrufen könnte, und dass der Button sicher mit einer geringen Baudrate auskommen würde? Allzuweit sollte man es wohl nicht treiben.
Benutzeravatar
sparrow
User
Beiträge: 4536
Registriert: Freitag 17. April 2009, 10:28

:shock: :roll: :K
Antworten