Schleife mit Thread mit Button beenden

Fragen zu Tkinter.
Antworten
davew
User
Beiträge: 2
Registriert: Montag 28. Februar 2022, 11:14

Hallo zusammen, bin gerade dabei eine Netzwerktestung mit Python zu automatisieren und benutze dazu fping. In meiner GUI starte ich mit dem Start Button eine funktion die fping immer wieder aufruft und einige Pakete senden lässt. Wie kann ich jetzt diese Schleife beenden? Ich packe unten mal auszugsweise den Code dazu.

Code: Alles auswählen

class meinThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        fping(stop)
        
stop = False

def startButton():
    startButton.config(state=DISABLED)
    t1 = meinThread()
    t1.start()

def stopButton():
    checkForStop()

def endButton():
    pass

def fping(stop):
    while stop == False:
        command = 'Fping 192.168.1.10 -t 5 -s 500 -n 5 -L output.txt'
        process = subprocess.Popen(command, shell=True)

def checkForStop():
    global stop
    stop = True
   
    startButton = Button(window,text="Start",
                         relief='flat',background=bg,
                         fg='white',
                         width=10,
                         font=labelFont,
                         activebackground="#666666",
                         activeforeground='white',
                         command=startButton)
    stopButton = Button(window,text="Stop",
                        relief='flat',background=bg,
                         fg='white',
                         width=10,
                         font=labelFont,
                         activebackground="#666666",
                         activeforeground='white',
                         command=stopButton)
    beendenButton = Button(window,text="Beenden",
                        relief='flat',background=bg,
                         fg='white',
                         width=10,
                         font=labelFont,
                         activebackground="#666666",
                         activeforeground='white'
                         )

Danke schon mal für die Hilfe, ich bin ziemlich neu im Programmieren und schlag mich jetzt schon ne ganze Weile damit rum
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Importe fehlen.
Wenn irgendwas das Präfix my/mein hat, dann ist das unsinnig, weil ein "mein" keinen Mehrwert liefert. Klassen schreibt man auch mit großem Anfangsbuchstaben, also MeinThread, aber besser FPingThread; die Threadklasse ist übrigens überflüssig, weil man bei Thread als target=fping die Funktion, die run starten soll, direkt angeben kann.
Benutze niemals shell=True bei subprocess, sondern übergebe das Commando als Liste. Du startest ständig neue Prozesse, so dass Dein System in kürze lahm gelegt ist, weil zu viele fPing-Prozesse gestartet wurden. Du mußt auf das Ende des Prozesses warten, am besten, benutze subprocess.run.

Variablennamen schreibt man wie Funktionsnamen komplett klein, also start_fping, oder stop_fping. Du hast Deinen Code nie getestet, weil die Funktion startButton ind checkForStop durch die lokale Variable des selben Namens überdeckt wird.
Eine Funktion muß alles, was sie braucht, über ihre Argumente bekommen, benutze niemals `global`.
Bei `checkForStop` fehlen window, bg und labelFont. Da die Buttons nirgends platziert werden, sind sie nutzlos. Der Code zum Aufruf von checkForStop fehlt auch. Der Name checkForStop ist sehr verwirrend, weil da gar nichts gecheckt wird, sondern nur Buttons erzeugt werden.
Wenn man mit einem Thread kommunizieren möchte, braucht man die passenden Datenstrukturen. Hier zum Beispiel ein Event.

Für GUI-Programme braucht man zwangsläufig Klassendefinitionen, um z.B. das Event-Objekt von einer Button-Methode zur nächsten zu speichern.

Hier das ganze ohne GUI, weil es ja kein eigentliches GUI-Problem ist:

Code: Alles auswählen

from threading import Thread, Event
import time

def fping(stop_event):
    while not stop_event.is_set():
        subprocess.run(['Fping', '192.168.1.10', '-t', '5', '-s', '500', '-n', '5' ,'-L', 'output.txt'])


def main():
    stop_event = Event()
    Thread(target=fping, args=(stop_event,)).start()
    time.sleep(10)
    stop_event.set()

if __name__ == "__main__":
    main()
davew
User
Beiträge: 2
Registriert: Montag 28. Februar 2022, 11:14

Naja ich habe ja nur Auszüge aus dem Programm kopiert, das ganze wäre rund 300 Zeilen lang, also die Importe hab ich alle drin.
Danke auf jeden Fall für die ganzen Hinweise, ich werde noch mal alles überarbeiten und es objektorientiert umschreiben. Und tut mir leid das alles inzwischen unlogisch klingt, ich hab die letzten Tage schon einige Stunden an allem gesessen und viel rumprobiert und wieder gelöscht. Und danke für die Tipps zur besseren Lesbarkeit.
Antworten