È possibile terminare un thread in esecuzione senza impostare / controllare eventuali flag / semafori / ecc.?
È possibile terminare un thread in esecuzione senza impostare / controllare eventuali flag / semafori / ecc.?
Risposte:
In genere è un cattivo modello uccidere un thread bruscamente, in Python e in qualsiasi lingua. Pensa ai seguenti casi:
Il modo migliore di gestirlo se te lo puoi permettere (se gestisci i tuoi thread) è avere un flag exit_request che ogni thread controlla a intervalli regolari per vedere se è il momento di uscire.
Per esempio:
import threading
class StoppableThread(threading.Thread):
"""Thread class with a stop() method. The thread itself has to check
regularly for the stopped() condition."""
def __init__(self, *args, **kwargs):
super(StoppableThread, self).__init__(*args, **kwargs)
self._stop_event = threading.Event()
def stop(self):
self._stop_event.set()
def stopped(self):
return self._stop_event.is_set()
In questo codice, dovresti chiamare stop()
il thread quando vuoi che esca e aspettare che il thread esca correttamente usando join()
. Il thread dovrebbe controllare il flag di stop a intervalli regolari.
In alcuni casi, tuttavia, è necessario eliminare un thread. Un esempio è quando si esegue il wrapping di una libreria esterna occupata per chiamate lunghe e si desidera interromperla.
Il codice seguente consente (con alcune restrizioni) di generare un'eccezione in un thread Python:
def _async_raise(tid, exctype):
'''Raises an exception in the threads with id tid'''
if not inspect.isclass(exctype):
raise TypeError("Only types can be raised (not instances)")
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid),
ctypes.py_object(exctype))
if res == 0:
raise ValueError("invalid thread id")
elif res != 1:
# "if it returns a number greater than one, you're in trouble,
# and you should call it again with exc=NULL to revert the effect"
ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), None)
raise SystemError("PyThreadState_SetAsyncExc failed")
class ThreadWithExc(threading.Thread):
'''A thread class that supports raising exception in the thread from
another thread.
'''
def _get_my_tid(self):
"""determines this (self's) thread id
CAREFUL : this function is executed in the context of the caller
thread, to get the identity of the thread represented by this
instance.
"""
if not self.isAlive():
raise threading.ThreadError("the thread is not active")
# do we have it cached?
if hasattr(self, "_thread_id"):
return self._thread_id
# no, look for it in the _active dict
for tid, tobj in threading._active.items():
if tobj is self:
self._thread_id = tid
return tid
# TODO: in python 2.6, there's a simpler way to do : self.ident
raise AssertionError("could not determine the thread's id")
def raiseExc(self, exctype):
"""Raises the given exception type in the context of this thread.
If the thread is busy in a system call (time.sleep(),
socket.accept(), ...), the exception is simply ignored.
If you are sure that your exception should terminate the thread,
one way to ensure that it works is:
t = ThreadWithExc( ... )
...
t.raiseExc( SomeException )
while t.isAlive():
time.sleep( 0.1 )
t.raiseExc( SomeException )
If the exception is to be caught by the thread, you need a way to
check that your thread has caught it.
CAREFUL : this function is executed in the context of the
caller thread, to raise an excpetion in the context of the
thread represented by this instance.
"""
_async_raise( self._get_my_tid(), exctype )
(Basato su thread Killable di Tomer Filiba. La citazione sul valore restituito di PyThreadState_SetAsyncExc
sembra provenire da una vecchia versione di Python .)
Come notato nella documentazione, questo non è un proiettile magico perché se il thread è occupato fuori dall'interprete Python, non intercetterà l'interruzione.
Un buon modello di utilizzo di questo codice è fare in modo che il thread rilevi un'eccezione specifica ed esegua la pulizia. In questo modo, è possibile interrompere un'attività e avere comunque una corretta pulizia.
SO_REUSEADDR
opzione socket per evitare Address already in use
errori.
None
invece che 0
per il res != 1
caso, e ho dovuto chiamare ctypes.c_long(tid)
e passarlo direttamente a qualsiasi funzione di tipo CTS anziché a quella corrente.
Non esiste un'API ufficiale per farlo, no.
È necessario utilizzare l'API della piattaforma per terminare il thread, ad esempio pthread_kill o TerminateThread. È possibile accedere a tale API, ad esempio tramite pythonwin o tramite ctypes.
Si noti che questo è intrinsecamente pericoloso. Probabilmente porterà a rifiuti non collezionabili (dalle variabili locali dei frame dello stack che diventano rifiuti) e potrebbe portare a deadlock, se il thread che viene ucciso ha il GIL nel punto in cui viene ucciso.
Una multiprocessing.Process
lattinap.terminate()
Nei casi in cui voglio uccidere un thread, ma non voglio usare flag / lock / segnali / semafori / eventi / qualunque cosa, promuovo i thread a processi completi. Per il codice che utilizza solo pochi thread, l'overhead non è poi così male.
Ad esempio, è utile per terminare facilmente i "thread" di supporto che eseguono I / O di blocco
La conversione è banale: nel codice correlato sostituisci tutto threading.Thread
con multiprocessing.Process
e tutti queue.Queue
con multiprocessing.Queue
e aggiungi le chiamate richieste p.terminate()
al tuo processo genitore che vuole uccidere suo figliop
Vedere la documentazione di Python permultiprocessing
.
multiprocessing
è carino, ma tieni presente che gli argomenti vengono messi in discussione nel nuovo processo. Quindi, se uno degli argomenti è qualcosa di non selezionabile (come un logging.log
), potrebbe non essere una buona idea usare multiprocessing
.
multiprocessing
gli argomenti vengono decapitati al nuovo processo su Windows, ma Linux usa il fork per copiarli (Python 3.7, incerto su quali altre versioni). Quindi finirai con il codice che funziona su Linux ma genera errori di pickle su Windows.
multiprocessing
con la registrazione è un affare complicato. Devi usare QueueHandler
(vedi questo tutorial ). L'ho imparato a mie spese.
Se stai cercando di terminare l'intero programma, puoi impostare il thread come "demone". vedi Thread.daemon
Come altri hanno già detto, la norma è quella di impostare un flag di stop. Per qualcosa di leggero (nessuna sottoclasse di Thread, nessuna variabile globale), un callback lambda è un'opzione. (Nota tra parentesi if stop()
.)
import threading
import time
def do_work(id, stop):
print("I am thread", id)
while True:
print("I am thread {} doing something".format(id))
if stop():
print(" Exiting loop.")
break
print("Thread {}, signing off".format(id))
def main():
stop_threads = False
workers = []
for id in range(0,3):
tmp = threading.Thread(target=do_work, args=(id, lambda: stop_threads))
workers.append(tmp)
tmp.start()
time.sleep(3)
print('main: done sleeping; time to stop the threads.')
stop_threads = True
for worker in workers:
worker.join()
print('Finis.')
if __name__ == '__main__':
main()
La sostituzione print()
con una pr()
funzione che scarica sempre ( sys.stdout.flush()
) può migliorare la precisione dell'output della shell.
(Testato solo su Windows / Eclipse / Python3.3)
pr()
funzione?
Questo è basato su thread2 - thread killable (ricetta Python)
Devi chiamare PyThreadState_SetasyncExc (), che è disponibile solo attraverso i tipi.
Questo è stato testato solo su Python 2.7.3, ma è probabile che funzioni con altre versioni 2.x recenti.
import ctypes
def terminate_thread(thread):
"""Terminates a python thread from another thread.
:param thread: a threading.Thread instance
"""
if not thread.isAlive():
return
exc = ctypes.py_object(SystemExit)
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(
ctypes.c_long(thread.ident), exc)
if res == 0:
raise ValueError("nonexistent thread id")
elif res > 1:
# """if it returns a number greater than one, you're in trouble,
# and you should call it again with exc=NULL to revert the effect"""
ctypes.pythonapi.PyThreadState_SetAsyncExc(thread.ident, None)
raise SystemError("PyThreadState_SetAsyncExc failed")
KeyboardInterrupt
modo che abbiano la possibilità di ripulire. Se sono ancora bloccati dopo, allora SystemExit
è appropriato o semplicemente uccide il processo da un terminale.
pthread_cleanup_push()/_pop()
, sarebbe molto difficile implementarlo correttamente e rallenterebbe notevolmente l'interprete.
Non dovresti mai uccidere forzatamente un thread senza collaborare con esso.
L'uccisione di un thread rimuove qualsiasi garanzia che provi / infine blocchi impostati in modo da poter lasciare i blocchi bloccati, i file aperti, ecc.
L'unica volta in cui puoi sostenere che uccidere forzatamente i thread è una buona idea è quello di uccidere un programma velocemente, ma mai singoli thread.
In Python, semplicemente non puoi uccidere direttamente un thread.
Se NON hai davvero bisogno di avere un Thread (!), Quello che puoi fare, invece di usare il pacchetto threading , è usare il pacchetto multiprocessore . Qui, per terminare un processo, puoi semplicemente chiamare il metodo:
yourProcess.terminate() # kill the process!
Python ucciderà il tuo processo (su Unix attraverso il segnale SIGTERM, mentre su Windows attraverso la TerminateProcess()
chiamata). Fai attenzione ad usarlo mentre usi una coda o una pipe! (potrebbe corrompere i dati nella coda / pipe)
Si noti che multiprocessing.Event
e e multiprocessing.Semaphore
funzionano esattamente allo stesso modo di threading.Event
e threading.Semaphore
rispettivamente. In effetti, i primi sono cloni di questi ultimi.
Se hai davvero bisogno di usare un thread, non c'è modo di ucciderlo direttamente. Quello che puoi fare, tuttavia, è usare un "thread demone" . In effetti, in Python, un thread può essere contrassegnato come demone :
yourThread.daemon = True # set the Thread as a "daemon thread"
Il programma principale verrà chiuso quando non rimangono più thread non daemon attivi. In altre parole, quando il tuo thread principale (che è, ovviamente, un thread non daemon) finirà le sue operazioni, il programma uscirà anche se ci sono ancora alcuni thread daemon funzionanti.
Nota che è necessario impostare un thread come daemon
prima start()
che venga chiamato il metodo!
Ovviamente puoi, e dovresti, usarlo daemon
anche con multiprocessing
. Qui, quando termina il processo principale, tenta di terminare tutti i suoi processi figlio demoniaci.
Infine, si prega, si noti che sys.exit()
e os.kill()
non sono scelte.
Puoi uccidere un thread installando la traccia nel thread che uscirà dal thread. Vedi link allegato per una possibile implementazione.
Se si sta chiamando esplicitamente time.sleep()
come parte del filo (diciamo polling qualche servizio esterno), con un miglioramento dal metodo di Phillipe è quello di utilizzare il timeout nel event
's wait()
metodo ovunque tusleep()
Per esempio:
import threading
class KillableThread(threading.Thread):
def __init__(self, sleep_interval=1):
super().__init__()
self._kill = threading.Event()
self._interval = sleep_interval
def run(self):
while True:
print("Do Something")
# If no kill signal is set, sleep for the interval,
# If kill signal comes in while sleeping, immediately
# wake up and handle
is_killed = self._kill.wait(self._interval)
if is_killed:
break
print("Killing Thread")
def kill(self):
self._kill.set()
Quindi eseguirlo
t = KillableThread(sleep_interval=5)
t.start()
# Every 5 seconds it prints:
#: Do Something
t.kill()
#: Killing Thread
Il vantaggio di utilizzare wait()
invece di sleep()
ing e controllare regolarmente l'evento è che è possibile programmare in intervalli di sospensione più lunghi, il thread viene interrotto quasi immediatamente (quando si sarebbe altrimenti sleep()
ing) e, a mio avviso, il codice per la gestione dell'uscita è significativamente più semplice .
È meglio se non uccidi un thread. Un modo potrebbe essere quello di introdurre un blocco "try" nel ciclo del thread e generare un'eccezione quando si desidera interrompere il thread (ad esempio un'interruzione / ritorno / ... che interrompe il tuo per / while / ...). L'ho usato sulla mia app e funziona ...
È sicuramente possibile implementare un Thread.stop
metodo come mostrato nel seguente codice di esempio:
import sys
import threading
import time
class StopThread(StopIteration):
pass
threading.SystemExit = SystemExit, StopThread
class Thread2(threading.Thread):
def stop(self):
self.__stop = True
def _bootstrap(self):
if threading._trace_hook is not None:
raise ValueError('Cannot run thread with tracing!')
self.__stop = False
sys.settrace(self.__trace)
super()._bootstrap()
def __trace(self, frame, event, arg):
if self.__stop:
raise StopThread()
return self.__trace
class Thread3(threading.Thread):
def _bootstrap(self, stop_thread=False):
def stop():
nonlocal stop_thread
stop_thread = True
self.stop = stop
def tracer(*_):
if stop_thread:
raise StopThread()
return tracer
sys.settrace(tracer)
super()._bootstrap()
###############################################################################
def main():
test1 = Thread2(target=printer)
test1.start()
time.sleep(1)
test1.stop()
test1.join()
test2 = Thread2(target=speed_test)
test2.start()
time.sleep(1)
test2.stop()
test2.join()
test3 = Thread3(target=speed_test)
test3.start()
time.sleep(1)
test3.stop()
test3.join()
def printer():
while True:
print(time.time() % 1)
time.sleep(0.1)
def speed_test(count=0):
try:
while True:
count += 1
except StopThread:
print('Count =', count)
if __name__ == '__main__':
main()
La Thread3
classe sembra eseguire il codice circa il 33% più velocemente della Thread2
classe.
self.__stop
essere impostato nel thread. Si noti che come la maggior parte delle altre soluzioni qui, in realtà non interromperà una chiamata di blocco, poiché la funzione di traccia viene chiamata solo quando viene inserito un nuovo ambito locale. Vale anche la pena notare che è sys.settrace
veramente pensato per l'implementazione di debugger, profili, ecc. E come tale è considerato un dettaglio di implementazione di CPython e non è garantito che esista in altre implementazioni di Python.
Thread2
classe è che esegue il codice circa dieci volte più lentamente. Alcune persone potrebbero ancora trovarlo accettabile.
from ctypes import *
pthread = cdll.LoadLibrary("libpthread-2.15.so")
pthread.pthread_cancel(c_ulong(t.ident))
t è il tuo Thread
oggetto.
Leggi la fonte di Python ( Modules/threadmodule.c
e Python/thread_pthread.h
) puoi vedere che Thread.ident
è un pthread_t
tipo, quindi puoi fare qualsiasi cosa pthread
possa fare nell'uso di Python libpthread
.
La seguente soluzione alternativa può essere utilizzata per uccidere un thread:
kill_threads = False
def doSomething():
global kill_threads
while True:
if kill_threads:
thread.exit()
......
......
thread.start_new_thread(doSomething, ())
Questo può essere usato anche per terminare i thread, il cui codice è scritto in un altro modulo, dal thread principale. Possiamo dichiarare una variabile globale in quel modulo e usarla per terminare i thread generati in quel modulo.
Di solito lo uso per terminare tutti i thread all'uscita dal programma. Questo potrebbe non essere il modo perfetto per terminare i thread ma potrebbe aiutare.
Sono in ritardo a questo gioco, ma ho lottato con una domanda simile e quanto segue sembra sia risolvere perfettamente il problema per me E mi permette di fare un controllo dello stato del thread di base e di ripulirlo quando il sottoprocesso demone esce:
import threading
import time
import atexit
def do_work():
i = 0
@atexit.register
def goodbye():
print ("'CLEANLY' kill sub-thread with value: %s [THREAD: %s]" %
(i, threading.currentThread().ident))
while True:
print i
i += 1
time.sleep(1)
t = threading.Thread(target=do_work)
t.daemon = True
t.start()
def after_timeout():
print "KILL MAIN THREAD: %s" % threading.currentThread().ident
raise SystemExit
threading.Timer(2, after_timeout).start()
I rendimenti:
0
1
KILL MAIN THREAD: 140013208254208
'CLEANLY' kill sub-thread with value: 2 [THREAD: 140013674317568]
SystemExit
sul after_timeout
thread farebbe qualcosa al thread principale (che sta semplicemente aspettando che il primo esca in questo esempio)?
SystemExit
ha solo due proprietà speciali: non produce un traceback (quando un thread esce lanciandone uno) e se il thread principale esce lanciandone uno imposta lo stato di uscita (mentre attende comunque altri thread non daemon uscire).
Una cosa che voglio aggiungere è che se leggi la documentazione ufficiale nel threading lib Python , è consigliabile evitare l'uso di thread "demoniaci", quando non vuoi che i thread finiscano bruscamente, con la bandiera di cui parla Paolo Rovelli .
Dalla documentazione ufficiale:
I thread daemon vengono improvvisamente arrestati allo spegnimento. Le loro risorse (come file aperti, transazioni di database, ecc.) Potrebbero non essere rilasciate correttamente. Se vuoi che i tuoi thread si fermino con grazia, rendili non demonici e usa un meccanismo di segnalazione adatto come un Evento.
Penso che la creazione di thread daemonici dipenda dalla tua applicazione, ma in generale (e secondo me) è meglio evitare di ucciderli o renderli demoniaci. Nel multiprocessing puoi usareis_alive()
per verificare lo stato del processo e "terminare" per completarli (Inoltre si evitano problemi GIL). Ma puoi trovare più problemi, a volte, quando esegui il tuo codice in Windows.
E ricorda sempre che se hai "thread attivi", l'interprete Python sarà in esecuzione per aspettarli. (A causa di questo demone può aiutarti se la materia non finisce improvvisamente).
C'è una biblioteca costruita per questo scopo, basta . Sebbene siano ancora applicabili alcune delle stesse precauzioni elencate nel presente documento, almeno questa libreria presenta una tecnica regolare e ripetibile per raggiungere l'obiettivo dichiarato.
Mentre è piuttosto vecchio, questa potrebbe essere una soluzione utile per alcuni:
Un piccolo modulo che estende la funzionalità del modulo del threading: consente a un thread di generare eccezioni nel contesto di un altro thread. Alzando
SystemExit
, puoi finalmente uccidere i thread di Python.
import threading
import ctypes
def _async_raise(tid, excobj):
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(excobj))
if res == 0:
raise ValueError("nonexistent thread id")
elif res > 1:
# """if it returns a number greater than one, you're in trouble,
# and you should call it again with exc=NULL to revert the effect"""
ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
raise SystemError("PyThreadState_SetAsyncExc failed")
class Thread(threading.Thread):
def raise_exc(self, excobj):
assert self.isAlive(), "thread must be started"
for tid, tobj in threading._active.items():
if tobj is self:
_async_raise(tid, excobj)
return
# the thread was alive when we entered the loop, but was not found
# in the dict, hence it must have been already terminated. should we raise
# an exception here? silently ignore?
def terminate(self):
# must raise the SystemExit type, instead of a SystemExit() instance
# due to a bug in PyThreadState_SetAsyncExc
self.raise_exc(SystemExit)
Pertanto, consente a un "thread di generare eccezioni nel contesto di un altro thread" e in questo modo, il thread terminato può gestire la terminazione senza controllare regolarmente un flag di interruzione.
Tuttavia, secondo la sua fonte originale , ci sono alcuni problemi con questo codice.
- L'eccezione verrà sollevata solo durante l'esecuzione del bytecode python. Se il thread chiama una funzione di blocco nativa / incorporata, l'eccezione verrà sollevata solo quando l'esecuzione torna al codice Python.
- C'è anche un problema se la funzione integrata chiama internamente PyErr_Clear (), che annullerebbe effettivamente l'eccezione in sospeso. Puoi provare a sollevarlo di nuovo.
- Solo i tipi di eccezione possono essere sollevati in modo sicuro. Le istanze di eccezione possono causare comportamenti imprevisti e pertanto sono limitate.
- Ad esempio: t1.raise_exc (TypeError) e non t1.raise_exc (TypeError ("blah")).
- IMHO è un bug e l'ho segnalato come uno. Per maggiori informazioni, http://mail.python.org/pipermail/python-dev/2006-August/068158.html
- Ho chiesto di esporre questa funzione nel modulo thread incorporato, ma poiché ctypes è diventato una libreria standard (a partire da 2.5), e questa
funzionalità non è probabilmente indipendente dall'implementazione, potrebbe non essere
esposta.
Pieter Hintjens - uno dei fondatori del progetto ØMQ - afferma, usando ØMQ ed evitando primitive di sincronizzazione come blocchi, mutex, eventi ecc., È il modo più sicuro e sicuro per scrivere programmi multi-thread:
http://zguide.zeromq.org/py:all#Multithreading-with-ZeroMQ
Ciò include dire a un thread figlio che dovrebbe annullare il suo lavoro. Ciò avverrebbe dotando il thread di un socket ØMQ e eseguendo il polling su quel socket per un messaggio che dice che dovrebbe essere annullato.
Il collegamento fornisce anche un esempio sul codice Python multi-thread con ØMQ.
Supponendo che tu voglia avere più thread della stessa funzione, questa è IMHO l'implementazione più semplice per fermarne una per id:
import time
from threading import Thread
def doit(id=0):
doit.stop=0
print("start id:%d"%id)
while 1:
time.sleep(1)
print(".")
if doit.stop==id:
doit.stop=0
break
print("end thread %d"%id)
t5=Thread(target=doit, args=(5,))
t6=Thread(target=doit, args=(6,))
t5.start() ; t6.start()
time.sleep(2)
doit.stop =5 #kill t5
time.sleep(2)
doit.stop =6 #kill t6
La cosa bella è qui, puoi avere più funzioni uguali e diverse e fermarle tutte functionname.stop
Se si desidera avere un solo thread della funzione, non è necessario ricordare l'id. Basta fermarsi, se doit.stop
> 0.
Solo per sviluppare l'idea di @ SCB (che era esattamente quello di cui avevo bisogno) per creare una sottoclasse KillableThread con una funzione personalizzata:
from threading import Thread, Event
class KillableThread(Thread):
def __init__(self, sleep_interval=1, target=None, name=None, args=(), kwargs={}):
super().__init__(None, target, name, args, kwargs)
self._kill = Event()
self._interval = sleep_interval
print(self._target)
def run(self):
while True:
# Call custom function with arguments
self._target(*self._args)
# If no kill signal is set, sleep for the interval,
# If kill signal comes in while sleeping, immediately
# wake up and handle
is_killed = self._kill.wait(self._interval)
if is_killed:
break
print("Killing Thread")
def kill(self):
self._kill.set()
if __name__ == '__main__':
def print_msg(msg):
print(msg)
t = KillableThread(10, print_msg, args=("hello world"))
t.start()
time.sleep(6)
print("About to kill thread")
t.kill()
Naturalmente, come con @SBC, il thread non aspetta di eseguire un nuovo loop per arrestarsi. In questo esempio, vedresti il messaggio "Killing Thread" stampato subito dopo "About to kill thread" invece di attendere altri 4 secondi per completare il thread (dato che abbiamo già dormito per 6 secondi).
Il secondo argomento nel costruttore di KillableThread è la tua funzione personalizzata (print_msg qui). Gli argomenti Args sono gli argomenti che verranno utilizzati quando si chiama la funzione (("ciao mondo")) qui.
Come menzionato nella risposta di @ Kozyarchuk , l'installazione di trace funziona. Poiché questa risposta non conteneva alcun codice, ecco un esempio funzionante e pronto per l'uso:
import sys, threading, time
class TraceThread(threading.Thread):
def __init__(self, *args, **keywords):
threading.Thread.__init__(self, *args, **keywords)
self.killed = False
def start(self):
self._run = self.run
self.run = self.settrace_and_run
threading.Thread.start(self)
def settrace_and_run(self):
sys.settrace(self.globaltrace)
self._run()
def globaltrace(self, frame, event, arg):
return self.localtrace if event == 'call' else None
def localtrace(self, frame, event, arg):
if self.killed and event == 'line':
raise SystemExit()
return self.localtrace
def f():
while True:
print('1')
time.sleep(2)
print('2')
time.sleep(2)
print('3')
time.sleep(2)
t = TraceThread(target=f)
t.start()
time.sleep(2.5)
t.killed = True
Si ferma dopo aver stampato 1
e 2
. 3
non è stampato.
È possibile eseguire il comando in un processo e quindi ucciderlo utilizzando l'ID processo. Avevo bisogno di sincronizzare tra due thread uno dei quali non ritorna da solo.
processIds = []
def executeRecord(command):
print(command)
process = subprocess.Popen(command, stdout=subprocess.PIPE)
processIds.append(process.pid)
print(processIds[0])
#Command that doesn't return by itself
process.stdout.read().decode("utf-8")
return;
def recordThread(command, timeOut):
thread = Thread(target=executeRecord, args=(command,))
thread.start()
thread.join(timeOut)
os.kill(processIds.pop(), signal.SIGINT)
return;
Inizia il thread secondario con setDaemon (True).
def bootstrap(_filename):
mb = ModelBootstrap(filename=_filename) # Has many Daemon threads. All get stopped automatically when main thread is stopped.
t = threading.Thread(target=bootstrap,args=('models.conf',))
t.setDaemon(False)
while True:
t.start()
time.sleep(10) # I am just allowing the sub-thread to run for 10 sec. You can listen on an event to stop execution.
print('Thread stopped')
break
Questa è una cattiva risposta, vedere i commenti
Ecco come farlo:
from threading import *
...
for thread in enumerate():
if thread.isAlive():
try:
thread._Thread__stop()
except:
print(str(thread.getName()) + ' could not be terminated'))
Dagli qualche secondo quindi il tuo thread dovrebbe essere fermato. Controlla anche ilthread._Thread__delete()
metodo.
Consiglierei un thread.quit()
metodo per comodità. Ad esempio, se hai un socket nel tuo thread, ti consiglio di creare un quit()
metodo nella tua classe handle-handle, terminare il socket, quindi eseguire un thread._Thread__stop()
interno al tuo quit()
.
_Thread__stop()
semplicemente un thread come interrotto , in realtà non interrompe il thread! Non farlo mai. Avere una lettura .
Se hai davvero bisogno della possibilità di terminare un'attività secondaria, usa un'implementazione alternativa. multiprocessing
ed gevent
entrambi supportano l'uccisione indiscriminata di un "thread".
Il threading di Python non supporta la cancellazione. Non provarci nemmeno. È molto probabile che il tuo codice blocchi, corrompa o perda la memoria o abbia altri effetti "interessanti" difficili da debug involontari che si verificano raramente e non deterministicamente.