Programm mit Thread mit einem KeyboardInterrupt beenden

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
maksimilian
User
Beiträge: 77
Registriert: Freitag 2. November 2018, 20:59

Sonntag 21. Februar 2021, 20:19

Hallo Ihr,
folgendes Testprogramm

Code: Alles auswählen

from time import sleep
import threading
from concurrent import futures
#
def proc1():
    while True:
        sleep(1)
#          
thread1 = futures.ThreadPoolExecutor(max_workers=1)
thread1.submit(proc1)
try:
    while True:
        sleep(1)
except KeyboardInterrupt:
    print("Thread beenden")
    thread1.shutdown()
    exit()
Ich benötige 3 x Strg+C um das Programm zu beenden. Wie kann ich erreichen, dass es mit nur einem Strg+C funktioniert.

Traceback:

Code: Alles auswählen

^CThread beenden
^CTraceback (most recent call last):
  File "test-exception.py", line 16, in <module>
    sleep(1)
KeyboardInterrupt

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "test-exception.py", line 19, in <module>
    thread1.shutdown()
  File "/usr/lib/python3.7/concurrent/futures/thread.py", line 204, in shutdown
    t.join()
  File "/usr/lib/python3.7/threading.py", line 1032, in join
    self._wait_for_tstate_lock()
  File "/usr/lib/python3.7/threading.py", line 1048, in _wait_for_tstate_lock
    elif lock.acquire(block, timeout):
KeyboardInterrupt
^CError in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/usr/lib/python3.7/concurrent/futures/thread.py", line 40, in _python_exit
    t.join()
  File "/usr/lib/python3.7/threading.py", line 1032, in join
    self._wait_for_tstate_lock()
  File "/usr/lib/python3.7/threading.py", line 1048, in _wait_for_tstate_lock
    elif lock.acquire(block, timeout):
KeyboardInterrupt
Sirius3
User
Beiträge: 14430
Registriert: Sonntag 21. Oktober 2012, 17:20

Sonntag 21. Februar 2021, 20:36

Warum verwendest Du einen ThreadPool für eine Endlosschleife?
Normalerweise benutzt man da einen normalen Thread mit daemon=True.
Benutzeravatar
noisefloor
User
Beiträge: 3176
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: Görgeshausen
Kontaktdaten:

Montag 22. Februar 2021, 07:12

Hallo,

es gibt threading.Event, mit dem du einem einfache "Kommunikaiton" mit dem Thread machen kannst. Z.B. solange das Event nicht gesetzt ist läuft die Endlosschleife, wenn es gesetzt wird nicht mehr und Thread beendet sich.

Gruß, noisefloor
maksimilian
User
Beiträge: 77
Registriert: Freitag 2. November 2018, 20:59

Montag 22. Februar 2021, 11:21

Sirius3 hat geschrieben:
Sonntag 21. Februar 2021, 20:36
Warum verwendest Du einen ThreadPool für eine Endlosschleife?
Ganz einfach, weil ich es nicht besser weiß bzw. weil das in einer Literatur gefundenen Beispiel funktioniert. Ich implementiere gerade ein kleines Projekt, in welchem Interprozess-Kommunikation über eine Pipe in einem Thread läuft, welcher eintreffende Ereignisse in eine Queue schreibt, die in main abgearbeitet wird.
Sirius3 hat geschrieben:
Sonntag 21. Februar 2021, 20:36
Normalerweise benutzt man da einen normalen Thread mit daemon=True.
Wie sieht da die Syntax aus ?
maksimilian
User
Beiträge: 77
Registriert: Freitag 2. November 2018, 20:59

Montag 22. Februar 2021, 11:38

noisefloor hat geschrieben:
Montag 22. Februar 2021, 07:12
Hallo,

es gibt threading.Event, mit dem du einem einfache "Kommunikaiton" mit dem Thread machen kannst. Z.B. solange das Event nicht gesetzt ist läuft die Endlosschleife, wenn es gesetzt wird nicht mehr und Thread beendet sich.

Gruß, noisefloor
Warum brauche ich ein threading.even ? Im Thread kann man doch eine globale Variable abfragen. Außerdem: welchen Unterschied macht es, einen Tread sich selbst beenden zu lassen oder das mit thread.shutdown() von außen zu tun ?

Grundsätzlich noch die Frage zu meinem Beispiel: Warum braucht es 3x Ctrl+C ? Was läuft da ab ?
Benutzeravatar
noisefloor
User
Beiträge: 3176
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: Görgeshausen
Kontaktdaten:

Montag 22. Februar 2021, 13:06

Hallo,
Im Thread kann man doch eine globale Variable abfragen.
Weil man generell keine globalen Variablen beenden möchte.
Außerdem: welchen Unterschied macht es, einen Tread sich selbst beenden zu lassen oder das mit thread.shutdown() von außen zu tun ?
Zitat dazu aus der Python-Doku: "Note: Daemon threads are abruptly stopped at shutdown. Their resources (such as open files, database transactions, etc.) may not be released properly. If you want your threads to stop gracefully, make them non-daemonic and use a suitable signalling mechanism such as an Event."

Gruß, noisefloor
maksimilian
User
Beiträge: 77
Registriert: Freitag 2. November 2018, 20:59

Montag 22. Februar 2021, 20:29

threading.Event kann den Thread nicht aus einem Pipe-read werfen.

Ich habe jetzt auf "normalen" Thread umgestellt und das funktioniert auch. Wieder was gelernt.
Benutzeravatar
noisefloor
User
Beiträge: 3176
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: Görgeshausen
Kontaktdaten:

Dienstag 23. Februar 2021, 10:17

Hallo,
threading.Event kann den Thread nicht aus einem Pipe-read werfen.
threading.Event kann gar nichts, außer halt das Event setzen oder ein gesetztes Event löschen. _Was_ du daraus machst ist dein Sache, also wie dein Programm auf das gesetzte Event reagiert.

Gruß, noisefloor
maksimilian
User
Beiträge: 77
Registriert: Freitag 2. November 2018, 20:59

Donnerstag 25. Februar 2021, 19:58

maksimilian hat geschrieben:
Montag 22. Februar 2021, 20:29
threading.Event kann den Thread nicht aus einem Pipe-read werfen.
Aber ein Open in main() auf die Pipe.
Antworten