Script von Tkinter aus abbrechen

Fragen zu Tkinter.
Antworten
dominik123
User
Beiträge: 35
Registriert: Montag 10. Februar 2014, 08:48

Hallo,

ich rufe mittels Tkinter ein Hauptprogramm auf, welches wiederum sequentiell verschiedene Befehle in Unterprogrammen aufruft.
(unter anderem auch "warte 20min") Nun möchte ich das Programm durch einen Button in Tkinter jederzeit abbrechen können. Hierzu sollten noch einige Punkte abgearbeitet werden (Messgeräte beenden) und anschließend das Programm beendet werden.
Wie kann man so etwas realisieren? Eine einfache Abfrage im Hauptprogramm reicht wohl nicht aus, da das Programm dann erst nach abarbeiten des momentanen Unterprogrammes reagieren würde?

Vielen Dank im Voraus!
Grüße,
Dominik
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Du musst einfach Nachrichten an die zu beendenden Threads schicken und die müssen sich dann darum kümmern, dass sie sich selbst beenden. Du wirst ja irgend einen Kanal für Nachrichten vom Programm zu den Threads haben, wahrscheinlich eine Queue, die musst du dann nur noch um eine Nachricht erweitern.

Das Warten musst du dann natürlich ebenfalls über die Queue lösen, das ist aber kein Problem. Diese haben einen timeout-Parameter.
Das Leben ist wie ein Tennisball.
dominik123
User
Beiträge: 35
Registriert: Montag 10. Februar 2014, 08:48

Vielen Dank für die Antwort. Leider Arbeite ich zur Zeit nicht mit einer Queue. Wie müsste dies denn konkret aussehen?
Zur Zeit Starte ich lediglich per Button einen Thread in dem mein Hauptprogramm abgearbeitet wird...
dominik123
User
Beiträge: 35
Registriert: Montag 10. Februar 2014, 08:48

Gibt es eine Möglichkeit einen mittels threading.Thread() aufgerufenen Thread abrupt zu beenden? Da nur 1 Thread geöffnet ist, kann es nicht zu Problemen mit Variablen kommen...
BlackJack

@dominik123: Nein, das geht nicht. Prozesse kann man beenden, also zum Beispiel solche die mit dem `multiprocessing`-Modul gestartet wurden.

Das mit dem keine Probleme mit Variablen weil nur 1 Thread kann ich nicht nachvollziehen, denn wenn man einen Thread startet, dann hat man ja zwei nebenläufige Threads. Man hat ja in jedem Programm einen impliziten Thread in dem das Hauptprogramm läuft.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Wie du Kommunikation mittels Queues umsetzt kannst du an jeder Ecke nachlesen, hier im Forum gibt es dutzende Beiträge zum Thema. Da solltest du genug Information finden. Wenn du den Umgang mit Queues nicht beherrscht, dann stellt sich mir jedoch die Frage, wie du überhaupt mit Threads arbeitest, bzw. wie die Programmqualität in diesem Bereich ist. Warteschlangen sind auf dem Gebiet absolute Grundlagen. Threading ohne Queues ist fast wie Autofahren ohne Reifen. Es geht, aber besonders sinnvoll ist es nicht.
Das Leben ist wie ein Tennisball.
dominik123
User
Beiträge: 35
Registriert: Montag 10. Februar 2014, 08:48

Wäre es mit einem Prozess möglich, per Button das Unterprogramm zu starten und Abzubrechen? Momentan habe ich das Problem, dass mein GUI einfriert, wenn ich den Prozess starte...
BlackJack

@dominik123: Du kannst den Prozess starten und abbrechen. Wenn der nur das Unterprogramm beinhaltet, dann kannst Du das auf diese Weise starten und abbrechen.
dominik123
User
Beiträge: 35
Registriert: Montag 10. Februar 2014, 08:48

Momentan sieht mein Code zum Öffnen des Programmes folgender Maßen aus:

Code: Alles auswählen

def start_test():
    subprocess.call(call_mainprogram())
Allerdings friert mein GUI ein sobald ich diese Funktion starte. Wo liegt der Fehler?
Wäre es möglich diesen Prozess dann mittels "subprocess.terminate()" zu beenden?

Vielen Dank!
Grüße,
Dominik
BlackJack

@dominik123: Der Fehler liegt darin das Du `subprocess` anscheinend völlig falsch verwendest und das `call()` blockiert bis der externe Prozess abgearbeitet ist. Du musst das schon asynchron starten und Dir das `Popen`-Exemplar irgendwo merken, damit Du dann auch auf dem Objekt irgendwann die `terminate()`-Methode aufrufen kannst.
dominik123
User
Beiträge: 35
Registriert: Montag 10. Februar 2014, 08:48

Wie würde subprocess richtig angewendet denn aussehen? Stehe leider gerade auf dem Schlauch...
Bzw. wie kann ich zunächst einmal verhindern, dass das "call" blockiert?
BlackJack

@dominik123: `call()` blockiert. Das kann man nicht verhindern. Das muss ja warten bis der Prozess am Ende ist um den Rückgabecode vom Prozess zurückgeben zu können. Du musst das entweder in einem Thread verwenden, oder halt etwas anderes als `call()`. In der `subprocess`-Dokumentation sind ein ganzer Haufen Beispiele wenn ich mich recht erinnere.

Edit: `call()` in einem Thread zu starten bringt natürlich nichts, weil man da dann ja immer noch nicht an das `Popen`-Exemplar heran kommt um den Prozess zu beenden.
dominik123
User
Beiträge: 35
Registriert: Montag 10. Februar 2014, 08:48

Mit "subprocess.Popen(call_mainprogram())" bekomme ich leider das gleiche Problem...
Ich möchte nur in der Lage sein, das Programm "mainprogram.py" mittels Button zu öffnen, und bei Klicken eines anderen Button zu schließen...
BlackJack

@dominik123: Was ist denn dieses `call_mainprogramm()`? Das gibt doch hoffentlich die Liste zurück die der `Popen()`-Aufruf an der Stelle braucht, und führt nicht etwa das Unterprogramm aus‽ `Popen` startet *externe* Programme. Das und dessen Argumente muss man als Liste angeben. Hast Du die Dokumentation zu dem `subprocess`-Modul mal durchgearbeitet?
Antworten