Запускаю этот простой код:
import threading, time
class reqthread(threading.Thread):
def run(self):
for i in range(0, 10):
time.sleep(1)
print('.')
try:
thread = reqthread()
thread.start()
except (KeyboardInterrupt, SystemExit):
print('\n! Received keyboard interrupt, quitting threads.\n')
Но когда я запускаю его, он печатает
$ python prova.py
.
.
^C.
.
.
.
.
.
.
.
Exception KeyboardInterrupt in <module 'threading' from '/usr/lib/python2.6/threading.pyc'> ignored
На самом деле поток Python игнорировать мойCtrl+Cпрерывание клавиатуры и не печатает Received Keyboard Interrupt
. Зачем? То не так с этим кодом?
Essayer
try:
thread=reqthread()
thread.daemon=True
thread.start()
while True: time.sleep(100)
except (KeyboardInterrupt, SystemExit):
print '\n! Received keyboard interrupt, quitting threads.\n'
Sans l'appel à time.sleep
, le processus principal quitte trop tôt le bloc try...except
, de sorte que la variable KeyboardInterrupt
n'est pas interceptée. Ma première pensée a été d'utiliser thread.join
, mais cela semble bloquer le processus principal (en ignorant KeyboardInterrupt) jusqu'à ce que thread
soit terminé.
thread.daemon=True
entraîne la fin du thread à la fin du processus principal.
Pour résumer les modifications recommandées dans lescommentaires , les éléments suivants me conviennent:
try:
thread = reqthread()
thread.start()
while thread.isAlive():
thread.join(1) # not sure if there is an appreciable cost to this.
except (KeyboardInterrupt, SystemExit):
print '\n! Received keyboard interrupt, quitting threads.\n'
sys.exit()
Légère modification de la solution d'ubuntu.
Suppression de tread.daemon = True comme suggéré par Eric et remplacement de la boucle en veille par signal.pause ():
import signal
try:
thread=reqthread()
thread.start()
signal.pause() # instead of: while True: time.sleep(100)
except (KeyboardInterrupt, SystemExit):
print '\n! Received keyboard interrupt, quitting threads.\n'
Mettre le try ... except
dans chaque thread et une signal.pause()
dans truemain()
fonctionne pour moi.
Méfiez-vous des import lock quoique. Je suppose que c’est la raison pour laquelle Python ne résout pas ctrl-C par défaut.
Ma solution (hacky) consiste à monkey-patch Thread.join()
ainsi:
def initThreadJoinHack():
import threading, thread
mainThread = threading.currentThread()
assert isinstance(mainThread, threading._MainThread)
mainThreadId = thread.get_ident()
join_orig = threading.Thread.join
def join_hacked(threadObj, timeout=None):
"""
:type threadObj: threading.Thread
:type timeout: float|None
"""
if timeout is None and thread.get_ident() == mainThreadId:
# This is a HACK for Thread.join() if we are in the main thread.
# In that case, a Thread.join(timeout=None) would hang and even not respond to signals
# because signals will get delivered to other threads and Python would forward
# them for delayed handling to the main thread which hangs.
# See CPython signalmodule.c.
# Currently the best solution I can think of:
while threadObj.isAlive():
join_orig(threadObj, timeout=0.1)
else:
# In all other cases, we can use the original.
join_orig(threadObj, timeout=timeout)
threading.Thread.join = join_hacked