Wie beende ich einen Thread, wenn das Hauptprogramm endet?

84

Wenn ich einen Thread in einer Endlosschleife habe, gibt es eine Möglichkeit, ihn zu beenden, wenn das Hauptprogramm endet (z. B. wenn ich Ctrl+ drücke C)?

facha
quelle

Antworten:

46

Überprüfen Sie diese Frage. Die richtige Antwort enthält eine gute Erklärung, wie Threads richtig beendet werden können: Gibt es eine Möglichkeit, einen Thread in Python zu beenden ?

Um den Thread beim Keyboard Interrupt-Signal (Strg + C) anzuhalten, können Sie die Ausnahme "KeyboardInterrupt" abfangen und vor dem Beenden bereinigen. So was:

try:
    start_thread()  
except (KeyboardInterrupt, SystemExit):
    cleanup_stop_thread()
    sys.exit()

Auf diese Weise können Sie steuern, was zu tun ist, wenn das Programm abrupt beendet wird.

Sie können auch das integrierte Signalmodul verwenden, mit dem Sie Signalhandler einrichten können (in Ihrem speziellen Fall das SIGINT-Signal): http://docs.python.org/library/signal.html

rogeriopvl
quelle
Vielen Dank für Ihre Antwort. Ich hätte die Frage möglicherweise nicht richtig gestellt. In dem in dieser Frage gegebenen Beispiel war es weiterhin erforderlich, die stop () - Funktion des Threads auszuführen. Wenn ich ein Programm abnormal mit Strg + C beende, kann das nicht passieren. Meine Frage lautet also ein bisschen: "Wie rufe ich die Funktion mythread.stop () auf, wenn der Haupt-Thread-Fluss unterbrochen wird
?
1
Ist cleanup_stop_thread()eine globale Funktion, die ich verwenden kann? oder sollte ich es implementieren müssen?
Alper
@alper, ich denke, vielleicht war es nur ein Beispiel, das möglich ist, etwas zu implementieren. Sie sollten das implementieren
Leonardo Rick
98

Wenn Sie Ihre Worker-Threads zu Daemon-Threads machen, sterben diese ab, wenn alle Nicht-Daemon-Threads (z. B. der Haupt-Thread) beendet wurden.

http://docs.python.org/library/threading.html#threading.Thread.daemon

ʇSәɹoɈ
quelle
4
Vielen Dank für die einfache und präzise Antwort, das Standard-Threading. Der Thread-Daemon-Status isDaemon()ist False, setzen Sie ihn auf True by setDaemon(True).
Tong
3
Dies beantwortet die Frage und funktioniert einfach. Die Operation hat nicht gefragt, wie Threads im Allgemeinen sauber beendet werden sollen.
Johannes Overmann
1
isDaemon()und setDaemon()sind alte Getter / Setter (wie im oben verlinkten Dokument beschrieben), verwenden Sie einfach daemon=Trueinthreading.Thread()
fabio.sang
1
Beachten Sie, dass die Verwendung von Daemon-Threads andere Probleme verursachen kann und wahrscheinlich nicht das ist, was Sie hier wollen: stackoverflow.com/questions/20596918/…
Doopy
14

Versuchen Sie, den Sub-Thread als Daemon-Thread zu aktivieren.

Zum Beispiel:

Empfohlen:

from threading import Thread

t = Thread(target=<your-method>)
t.daemon = True  # This thread dies when main thread (only non-daemon thread) exits.
t.start()

In der Reihe:

t = Thread(target=<your-method>, daemon=True).start()

Alte API:

t.setDaemon(True)
t.start()

Wenn Ihr Haupt-Thread beendet wird ("dh wenn ich Ctrl+ drücke C"), werden auch andere Threads durch die obigen Anweisungen beendet.

Benyamin Jafari
quelle
1
Beachten Sie, dass die Verwendung von Daemon-Threads andere Probleme verursachen kann und wahrscheinlich nicht das ist, was Sie hier wollen: stackoverflow.com/questions/20596918/…
Doopy
12

Verwenden Sie das atexit- Modul der Python-Standardbibliothek, um "Beendigungs" -Funktionen zu registrieren, die (im Hauptthread) bei einer vernünftig "sauberen" Beendigung des Hauptthreads aufgerufen werden, einschließlich einer nicht erfassten Ausnahme wie z KeyboardInterrupt. Solche Beendigungsfunktionen können (obwohl unvermeidlich im Hauptthread!) Jede stopFunktion aufrufen , die Sie benötigen. Zusammen mit der Möglichkeit, einen Thread als daemonfestzulegen, erhalten Sie die Tools, um die von Ihnen benötigten Systemfunktionen richtig zu gestalten.

Alex Martelli
quelle
Beachten Sie, dass dieser Ansatz ohne Python-Threads in Python-Versionen vor 2.6.5 funktioniert hat , siehe Antwort auf stackoverflow.com/questions/3713360/… . Dies ist meiner Meinung nach unglücklich, da Daemon-Threads während des Herunterfahrens vor Python 3.4 ( bugs.python.org/issue19466 ) ein bisschen chaotisch sind . Wenn Sie anhalten und Ihre Daemon-Threads in Ihren Atexit-Handlern verbinden, sollte alles in Ordnung sein, und zwar auf (wahrscheinlich unbedeutende) Kosten für die Serialisierung Ihres Thread-Teardowns.
NeilenMarais
Beachten Sie, dass seltsame Dinge passieren können, wenn atexit.register()Aufrufe in Python-Modulen verschoben werden und Ihre Beendigungsprozedur nach der ersten ausgeführt wird multiprocessing. Ich habe in diesem Problem mit Queueund daemonThreads ausgeführt: "EOF-Fehler" beim Beenden des Programms unter Verwendung von Multiprocessing Queue und Thread .
Delgan
Anscheinend werden in modernen Python-Versionen wie 3.7.4+ die atexitHandler nicht aufgerufen, wenn Nicht-Daemon-Threads aktiv sind und der Haupt-Thread beendet wird. Siehe Skript beim Beenden hängen bleiben, wenn Sie atexit zum Beenden von Threads verwenden .
Martineau
9

Wenn Sie einen Thread wie diesen erzeugen - myThread = Thread(target = function)- und dann tun Sie es myThread.start(); myThread.join(). Wenn STRG-C initiiert wird, wird der Hauptthread nicht beendet, da er auf diesen blockierenden myThread.join()Aufruf wartet . Um dies zu beheben, geben Sie einfach eine Zeitüberschreitung für den Aufruf von .join () ein. Das Timeout kann so lange dauern, wie Sie möchten. Wenn Sie möchten, dass es unbegrenzt wartet, geben Sie einfach eine sehr lange Zeitüberschreitung ein, z. B. 99999. Es empfiehlt sich auch myThread.daemon = True, alle Threads zu beenden, wenn der Hauptthread (kein Daemon) beendet wird.

Milean
quelle
myThread.daemon = Trueist eine wunderbare Lösung für dieses Problem.
Brannon
5
@Brannon .daemon=Trueist keine feste Lösung. Überprüfen Sie diesen Thread für eine Erklärung: stackoverflow.com/a/20598791/5562492
Odyssee
2

Daemon-Threads werden unanständig beendet, sodass keine Finalizer-Anweisungen ausgeführt werden. Eine mögliche Lösung besteht darin, zu überprüfen, ob der Hauptthread anstelle der Endlosschleife aktiv ist.

ZB für Python 3:

while threading.main_thread().isAlive():
    do.you.subthread.thing()
gracefully.close.the.thread()

Siehe Überprüfen, ob der Haupt-Thread von einem anderen Thread noch aktiv ist .

umi
quelle