python signals copy-paste sigint

Python: Catch Ctrl-C comando. Preguntar "realmente quiero salir(y/n)", reanudar la ejecuciĆ³n si no hay



signals copy-paste (1)

Los manejadores de señales de python no parecen ser manejadores de señales reales; es decir, ocurren después del hecho, en el flujo normal y después de que el controlador C ya haya regresado. Por lo tanto, intentarías poner tu lógica de salida en el controlador de señales. Como el manejador de señales se ejecuta en el hilo principal, también bloqueará la ejecución allí.

Algo así parece funcionar bien.

import signal import time import sys def run_program(): while True: time.sleep(1) print("a") def exit_gracefully(signum, frame): # restore the original signal handler as otherwise evil things will happen # in raw_input when CTRL+C is pressed, and our signal handler is not re-entrant signal.signal(signal.SIGINT, original_sigint) try: if raw_input("/nReally quit? (y/n)> ").lower().startswith(''y''): sys.exit(1) except KeyboardInterrupt: print("Ok ok, quitting") sys.exit(1) # restore the exit gracefully handler here signal.signal(signal.SIGINT, exit_gracefully) if __name__ == ''__main__'': # store the original SIGINT handler original_sigint = signal.getsignal(signal.SIGINT) signal.signal(signal.SIGINT, exit_gracefully) run_program()

El código restaura el controlador de señal original durante la duración de raw_input ; raw_input sí no se puede volver a arrastrar, y volver a entrar llevará a RuntimeError: can''t re-enter readline en la time.sleep de time.sleep que se time.sleep desde time.sleep que es algo que no queremos ya que es más difícil de atrapar que KeyboardInterrupt . Más bien, permitimos que 2 Ctrl-C consecutivas aumenten KeyboardInterrupt .

Tengo un programa que puede tener una ejecución larga. En el módulo principal tengo lo siguiente:

import signal def run_program() ...time consuming execution... def Exit_gracefully(signal, frame): ... log exiting information ... ... close any open files ... sys.exit(0) if __name__ == ''__main__'': signal.signal(signal.SIGINT, Exit_gracefully) run_program()

Esto funciona bien, pero me gustaría tener la posibilidad de pausar la ejecución al capturar SIGINT, preguntar al usuario si realmente desea salir y reanudar donde lo dejé en run_program () si deciden que no quieren salir.

La única forma en que puedo pensar en hacer esto es ejecutar el programa en un subproceso separado, manteniendo el subproceso principal en espera y listo para capturar SIGINT. Si el usuario desea salir del hilo principal, puede realizar una limpieza y eliminar el hilo secundario.

¿Hay alguna forma más simple?