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?