Come terminare un thread quando termina il programma principale?


Risposte:


46

Controlla questa domanda. La risposta corretta ha un'ottima spiegazione su come terminare i thread nel modo giusto: esiste un modo per uccidere un thread in Python?

Per fermare il thread al segnale di interruzione della tastiera (ctrl + c) puoi catturare l'eccezione "KeyboardInterrupt" e ripulire prima di uscire. Come questo:

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

In questo modo puoi controllare cosa fare ogni volta che il programma viene interrotto bruscamente.

Puoi anche utilizzare il modulo di segnale integrato che ti consente di configurare i gestori di segnali (nel tuo caso specifico il segnale SIGINT): http://docs.python.org/library/signal.html


Grazie mille per la tua risposta. Potrei non aver espresso correttamente la domanda. Nell'esempio fornito in quella domanda era ancora necessario eseguire la funzione stop () del thread. Quando chiudo un programma in modo anomalo con ctrl + C, ciò non può accadere. Quindi, la mia domanda è un po 'come "come posso chiamare la funzione mythread.stop () se il flusso del thread principale viene interrotto"
facha

1
È cleanup_stop_thread()una funzione globale che posso usare? o dovrei aver bisogno di implementarlo?
alper

@alper, penso che forse era solo un esempio che è possibile implementare qualcosa. Dovresti implementarlo
Leonardo Rick

100

Se crei dei thread daemon dei tuoi thread di lavoro, moriranno quando tutti i tuoi thread non daemon (ad esempio il thread principale) saranno terminati.

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


4
Grazie per la risposta semplice e precisa, lo stato del demone threading di default isDaemon()è False, impostalo True con setDaemon(True).
Tong

3
Questo risponde alla domanda e funziona. L'operazione non ha chiesto come chiudere i thread in modo pulito in generale.
Johannes Overmann

1
isDaemon()e setDaemon()sono vecchi getter / setter (come da documento collegato sopra), basta usare daemon=Trueinthreading.Thread()
fabio.sang

1
Nota che l'utilizzo di thread demoni può causare altri problemi e non è probabilmente ciò che si vuole qui: stackoverflow.com/questions/20596918/...
Doopy

Per evitare di utilizzare thread daemon e uccidere i thread in modo pulito, vedere stackoverflow.com/questions/58910372/…
utente

15

Prova ad abilitare il thread secondario come thread daemon.

Per esempio:

Consigliato:

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 linea:

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

Vecchia API:

t.setDaemon(True)
t.start()

Quando il thread principale termina ("cioè quando premo Ctrl+ C"), anche gli altri thread verranno interrotti dalle istruzioni precedenti.


1
Nota che l'utilizzo di thread demoni può causare altri problemi e, probabilmente, non sono ciò che si vuole qui: stackoverflow.com/questions/20596918/...
Doopy

12

Usa il modulo atexit della libreria standard di Python per registrare le funzioni di "terminazione" che vengono chiamate (sul thread principale) su qualsiasi terminazione ragionevolmente "pulita" del thread principale, inclusa un'eccezione non rilevata come KeyboardInterrupt. Tali funzioni di terminazione possono (sebbene inevitabilmente nel thread principale!) Chiamare qualsiasi stopfunzione richiesta; insieme alla possibilità di impostare un thread come daemon, che ti dà gli strumenti per progettare correttamente le funzionalità di sistema di cui hai bisogno.


Si noti che questo approccio ha funzionato senza richiedere thread daemonizzati nelle versioni di Python precedenti alla 2.6.5, vedere la risposta a stackoverflow.com/questions/3713360/… . Questo è un peccato IMHO, dal momento che i thread del demone durante l'arresto sono un po 'un disastro prima di python 3.4 ( bugs.python.org/issue19466 ). Se ti fermi e unisci i tuoi thread daemon nei tuoi gestori atexit, tutto dovrebbe andare bene, al costo (probabilmente insignificante) di serializzare il tuo smontaggio del thread.
NeilenMarais

Siate consapevoli che possono accadere cose strane a causa di atexit.register()chiamate posticipate nei moduli Python, facendo sì che la vostra procedura di terminazione venga eseguita dopo multiprocessingquella di. Mi imbatto in questo problema che tratta Queuee daemonthread: "Errore EOF" all'uscita del programma utilizzando Queue e Thread multiprocessing .
Delgan

Apparentemente nelle versioni moderne di Python, come 3.7.4+, i atexitgestori non vengono chiamati quando i thread non daemon sono attivi e il thread principale esce. Vedere Script bloccato all'uscita quando si usa atexit per terminare i thread .
martineau

9

Se generi un filo in questo modo - myThread = Thread(target = function)- e poi fallo myThread.start(); myThread.join(). Quando viene avviato CTRL-C, il thread principale non si chiude perché è in attesa di quella myThread.join()chiamata di blocco . Per risolvere questo problema, è sufficiente inserire un timeout nella chiamata .join (). Il timeout può essere lungo quanto desideri. Se vuoi che attenda indefinitamente, metti un timeout molto lungo, come 99999. È anche una buona pratica farlo in myThread.daemon = Truemodo che tutti i thread escano quando il thread principale (non daemon) esce.


myThread.daemon = Trueè una meravigliosa soluzione a questo problema.
Brannon

5
@Brannon .daemon=Truenon è una soluzione solida. Controlla questo thread per una spiegazione: stackoverflow.com/a/20598791/5562492
Odyssee

2

I thread del demone vengono uccisi in modo sgraziato, quindi le istruzioni del finalizzatore non vengono eseguite. Una possibile soluzione è controllare se il thread principale è vivo anziché il ciclo infinito.

Ad esempio per Python 3:

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

Vedere Verificare se il thread principale è ancora attivo da un altro thread .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.