2009-09-28 12 views

risposta

33

Se tutti i thread tranne i principali sono daemon, l'approccio migliore è in genere thread.interrupt_main() - qualsiasi thread può utilizzarlo per generare un KeyboardInterrupt nel thread principale, che normalmente può portare a un'uscita ragionevolmente pulita dal thread principale (inclusi i finalizzatori nel thread principale che viene chiamato, ecc.).

Naturalmente, se ciò comporta un po 'di filo non-daemon mantenere l'intero processo vivo, è necessario follow con os._exit come Mark raccomanda - ma mi piacerebbe vedere che come ultima risorsa (un po' come un kill -9; -) perché termina le cose abbastanza bruscamente (i finalizzatori non vengono eseguiti, compresi i blocchi try/finally, i blocchi with, le funzioni atexit, ecc.).

+0

Il link è morto. – OrangeDog

28

Risposta breve: utilizzare os._exit.

Risposta lunga con l'esempio:

Diedi uno strattone e leggermente modificato un semplice esempio filettatura da a tutorial on DevShed:

import threading, sys, os 

theVar = 1 

class MyThread (threading.Thread): 

    def run (self): 

     global theVar 
     print 'This is thread ' + str (theVar) + ' speaking.' 
     print 'Hello and good bye.' 
     theVar = theVar + 1 
     if theVar == 4: 
      #sys.exit(1) 
      os._exit(1) 
     print '(done)' 

for x in xrange (7): 
    MyThread().start() 

Se si mantiene sys.exit(1) commentata, lo script moriranno dopo il terzo filo stampe fuori. Se si utilizza sys.exit(1) e si commenta os._exit(1), il terzo thread esegue non stampa (done) e il programma esegue tutti e sette i thread.

os._exit "normalmente dovrebbe essere utilizzato solo nel processo figlio dopo un fork()" - e un thread separato è abbastanza vicino a quello per il tuo scopo. Si noti inoltre che ci sono diversi valori enumerati elencati subito dopo os._exit in quella pagina di manuale, e si preferiscono quelli come argomenti a os._exit invece di numeri semplici come quelli usati nell'esempio sopra.

11

L'utilizzo di thread.interrupt_main() potrebbe non essere di aiuto in alcune situazioni. KeyboardInterrupt s vengono spesso utilizzati nelle applicazioni della riga di comando per uscire dal comando corrente o per pulire la riga di input.

Inoltre, os._exit interromperà immediatamente il processo senza eseguire alcun blocco finally nel proprio codice, che potrebbe essere pericoloso (ad esempio, i file e le connessioni non verranno chiusi).

La soluzione che ho trovato è registrare un gestore di segnale nel thread principale che solleva un'eccezione personalizzata. Usa il thread in background per attivare il segnale.

import signal 
import os 
import threading 
import time 


class ExitCommand(Exception): 
    pass 


def signal_handler(signal, frame): 
    raise ExitCommand() 


def thread_job(): 
    time.sleep(5) 
    os.kill(os.getpid(), signal.SIGUSR1) 


signal.signal(signal.SIGUSR1, signal_handler) 
threading.Thread(target=thread_job).start() # thread will fire in 5 seconds 
try: 
    while True: 
     user_input = raw_input('Blocked by raw_input loop ') 
     # do something with 'user_input' 
except ExitCommand: 
    pass 
finally: 
    print('finally will still run') 

domande correlate: