Was tu ich da eigentlich?

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
theoS
User
Beiträge: 108
Registriert: Dienstag 5. November 2019, 21:44

Hallo. Ich hänge mal wieder in der Verständnisschleife, drum bitte ich nicht um Verbesserung des Codes sondern darum mir vom Schlauch zu helfen, wo denn der Knick drin ist.
Ich verstehe von dem Code nämlich nicht ganz genau, was ich da eigentlich tu.
Ausgang ist mein Wunsch, auf ein bestimmtes Ereignist zu reagieren und meine grafische Oberfläche neu zu starten mit neuen Werten die die Knöpfe beschriften.
Dazu habe ich ein Beispiel gebastelt, dass ich das dann in dem anderen größeren Code versuchen kann umzusetzen.
So. Ich hab also zwei Stück Code, die ich in Threads laufen hab.
Ich hab eine Richtung in der der Code funktioniert, aber in der anderen Richtung tut sich leider wenig.
Und wieso geht das in eine Richtung, in die andere nicht?

Mir würde sehr helfen, wenn mir einfach mal jemand beschreiben könnte, was der Code in welche Richtung denn nun macht?
Danke.

Also, das ist der "consumer" (bin mir nicht sicher, da der eigentlich der Datenlieferant ist, ob das nicht eigentlich der producer ist...)

Code: Alles auswählen

import concurrent.futures
import queue
import threading
import buttonis

CONFIG_A =[
    (12, 6, 'Beispiel', 'Bsp 001', '1. Blubber'),
    (623, 4, 'Beispiel', 'Bsp 002', '2. Blubber' ),
    (91, 5, 'Beispiel', 'Bsp 003', '3. Blubber' ),
    (625, 7, 'Beispiel', 'Bsp 004', '4. Blubber'),
    (17, 8, 'Beispiel', 'Bsp 005', '5. Blubber'),
    (627, 413, 'Beispiel', 'Bsp 006','6. Blubber' ),
    (624, 1, 'Beispiel', 'Bsp 007', '7. Blubber' ),
    (13, 9, 'Beispiel', 'Bsp 008', '8. Blubber' )
    ]
CONFIG_B =[
    (12, 6, 'Neuland', 'Lubili 001', '1. Blubber'),
    (623, 4, 'Altland', 'Lubili 002', '2. Blubber' ),
    (91, 5, 'Hans', 'Lubili 003', '3. Blubber' ),
    (625, 7, 'Guck', 'Lubili 004', '4. Blubber'),
    (17, 8, 'In die', 'Lubili 005', '5. Blubber'),
    (627, 413, 'Luft', 'Lubili 006','6. Blubber' ),
    (624, 1, 'Rhabarber', 'Lubili 007', '7. Blubber' ),
    (13, 9, 'Dorf', 'Lubili 008', '8. Blubber' )
    ]

# wenn der consumer eine bestimmte message bekommt, dann soll er die Daten zur anderen Richtung schicken

def consumer(queue, event):
   
    while not event.is_set() or not queue.empty():
        message = queue.get()
        print(message, "von drüben")
        if message == 13:
            print(message, "in IF")
            message_to = CONFIG_B
            queue.put(message_to) 
            #event.set()
            


if __name__ == "__main__":
    
    config = CONFIG_A
    pipeline = queue.Queue(maxsize=10)
    event = threading.Event()
    with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
       
        executor.submit(buttonis.main, pipeline, event, config)
        executor.submit(consumer, pipeline, event)

    main()
und das ist die verienfachte Oberfläche...

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf8 -*-
import concurrent.futures
import queue
import threading
import tkinter as tk
from functools import partial
import logging



def on_click(row, queue, event):
  
    print(row[0], "in click: row[0]")    
    message = row[0]
    print("message in click:", message)
    print("event in click:", event)        
    queue.put(message)
    schau_ob_was_kommt(queue, event)

def schau_ob_was_kommt(queue, event):
    config = queue.get()
    print(config, "schau was kommt")
    
   
def main(queue, event, config):
    
    root = tk.Tk()
    
     
    #config = queue.get() #wenn ich da irgendwas davon in dem Teil aktiviere läuft der Thread aber keine Oberfläche mehr. :o(
    print(config, "config in Main buttonis")
    
    root.title("Auswahl der Label")
    root.config(background="#f2c618")
    button_frame = tk.Frame(root, width=1200, height=400)
    button_frame.grid(row=0, column=0, padx=10, pady=30)    
    
    for index, entry in enumerate(config):
        row_index, column_index = divmod(index, 4)
        
        tk.Button(
            button_frame,
            text="{}\n{}".format(entry[1], entry[2]),
            bg="#f2c618",
            width=15,
            height=10,
            command=partial(on_click, entry, queue, event),            
            ).grid(row=row_index, column=column_index, padx=0, pady=0)


        
    root.mainloop()

        
if __name__ == '__main__':

    main()
Benutzeravatar
__blackjack__
User
Beiträge: 13268
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@theoS: Du hast in beiden Threads `put()`- und `get()`-Aufrufe auf die selbe Queue. Das ist falsch. So eine Queue weiss nichts von Threads, es ist also nicht so das Werte die in einem Thread per `put()` hinzugefügt wurden auf magische Weise nur von `get()`-Aufrufen in einem anderen Thread geliefert werden. Wenn Du Kommunikation zwischen zwei Threads in beide Richtungen haben willst, dann brauchst Du zwei Queues.
Please call it what it is: copyright infringement, not piracy. Piracy takes place in international waters, and involves one or more of theft, murder, rape and kidnapping. Making an unauthorized copy of a piece of software is not piracy, it is an infringement of a government-granted monopoly.
Sirius3
User
Beiträge: 17844
Registriert: Sonntag 21. Oktober 2012, 17:20

GUIs, wie tkinter, dürfen nur im Hauptthread laufen. Die Nutzung des ThreadPoolExecutor ist also falsch, auch wenn alles scheinbar funktioniert, kann es halt doch zu subtilen Fehlern kommen.
Wie schon bei der anderen Diskussion mit Dir würde ich auch gar nicht viel im parallel laufend Thread machen, sondern nur die Information an die GUI schicken, dass jetzt ein neuer USB-Stick eingesteckt wurde. Dann ist die Kommunikation auch nur unidirektional.
Antworten