¿Cómo salir de toda la aplicación desde un hilo de Python?

¿Cómo puedo salir de toda mi aplicación Python desde uno de sus hilos? sys.exit () solo termina el hilo en el que se llama, por lo que no sirve de ayuda.

No me gustaría usar una solución os.kill (), ya que no está muy limpio.

Related of "¿Cómo salir de toda la aplicación desde un hilo de Python?"

Si todos los subprocesos, excepto los principales, son demonios, el mejor enfoque es generalmente thread.interrupt_main () : cualquier subproceso puede usarlo para subir un KeyboardInterrupt en el subproceso principal, que normalmente puede llevar a una salida razonablemente limpia del subproceso principal ( Incluyendo los finalizadores en el hilo principal que se llama, etc).

Por supuesto, si esto resulta en un hilo no daemon que mantiene vivo todo el proceso, debe os._exit con os._exit como Mark recomienda, pero lo vería como el último recurso (algo así como un kill -9 ; -) porque termina las cosas con bastante brusquedad (los finalizadores no se ejecutan, incluidos los bloques try/finally , with bloques, funciones atexit , etc.).

Respuesta corta: use os._exit .

Respuesta larga con ejemplo:

Tiré y modifiqué ligeramente un ejemplo de subprocesamiento simple de un tutorial en 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() 

Si mantiene sys.exit(1) , el script morirá después de que se imprima el tercer hilo. Si usa sys.exit(1) y comenta os._exit(1) , el tercer hilo no se imprime (done) , y el progtwig se ejecuta a través de los siete hilos.

os._exit “normalmente solo debe usarse en el proceso hijo después de un fork ()” – y un hilo separado es lo suficientemente cercano para su propósito. También tenga en cuenta que hay varios valores enumerados justo después de os._exit en esa página del manual, y debería preferirlos como argumentos a os._exit lugar de números simples como los que he usado en el ejemplo anterior.

El uso de thread.interrupt_main() puede no ayudar en alguna situación. KeyboardInterrupt se usan a menudo en aplicaciones de línea de comandos para salir del comando actual o para limpiar la línea de entrada.

Además, os._exit eliminará el proceso inmediatamente sin ejecutar ningún bloque os._exit en su código, lo que puede ser peligroso (los archivos y las conexiones no se cerrarán, por ejemplo).

La solución que encontré es registrar un controlador de señal en el hilo principal que genera una excepción personalizada. Usa el hilo de fondo para disparar la señal.

 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') 

Preguntas relacionadas:

  • ¿Por qué sys.exit () no sale cuando se llama dentro de un hilo en Python?
  • Python: ¿Cómo salir de CLI cuando se atasca en el locking de raw_input?