tipos excepciones diferentes python

excepciones - ¿Cómo evitar que un bloque de código sea interrumpido por KeyboardInterrupt en Python?



raise python (4)

Coloque la función en un hilo y espere a que el hilo termine.

Los hilos de Python no se pueden interrumpir, excepto con una API especial.

import time from threading import Thread def noInterrupt(): for i in xrange(4): print i time.sleep(1) a = Thread(target=noInterrupt) a.start() a.join() print "done" 0 1 2 3 Traceback (most recent call last): File "C:/Users/Admin/Desktop/test.py", line 11, in <module> a.join() File "C:/Python26/lib/threading.py", line 634, in join self.__block.wait() File "C:/Python26/lib/threading.py", line 237, in wait waiter.acquire() KeyboardInterrupt

¿Ves cómo se aplazó la interrupción hasta que terminó el hilo?

Aquí se adapta a su uso:

import time from threading import Thread def noInterrupt(path, obj): try: file = open(path, ''w'') dump(obj, file) finally: file.close() a = Thread(target=noInterrupt, args=(path,obj)) a.start() a.join()

Estoy escribiendo un programa que almacena algunos resultados a través del módulo pickle. Lo que sucede en este momento es que si pulso ctrl-c mientras se realiza la operación de dump , el dump se interrumpe y el archivo resultante se corrompe (es decir, solo se escribe parcialmente, por lo que no se puede load nuevo).

¿Hay alguna forma de hacer que el dump , o en general un bloque de código, sea ininterrumpible? Mi solución actual se ve algo como esto:

try: file = open(path, ''w'') dump(obj, file) file.close() except KeyboardInterrupt: file.close() file.open(path,''w'') dump(obj, file) file.close() raise

Parece una tontería reiniciar la operación si se interrumpe, por lo que estoy buscando una forma de diferir la interrupción. ¿Cómo hago esto?


El siguiente es un administrador de contexto que adjunta un controlador de señal para SIGINT . Si se llama al manejador de señales del administrador de contexto, la señal se retrasa al pasar la señal solo al manejador original cuando el gestor de contexto finaliza.

import signal import logging class DelayedKeyboardInterrupt(object): def __enter__(self): self.signal_received = False self.old_handler = signal.signal(signal.SIGINT, self.handler) def handler(self, sig, frame): self.signal_received = (sig, frame) logging.debug(''SIGINT received. Delaying KeyboardInterrupt.'') def __exit__(self, type, value, traceback): signal.signal(signal.SIGINT, self.old_handler) if self.signal_received: self.old_handler(*self.signal_received) with DelayedKeyboardInterrupt(): # stuff here will not be interrupted by SIGINT critical_code()


En mi opinión, el uso de hilos para esto es una exageración. Puede asegurarse de que el archivo se esté guardando correctamente simplemente haciéndolo en un bucle hasta que se realice una escritura exitosa:

def saveToFile(obj, filename): file = open(filename, ''w'') cPickle.dump(obj, file) file.close() return True done = False while not done: try: done = saveToFile(obj, ''file'') except KeyboardInterrupt: print ''retry'' continue


Use el módulo de signal para deshabilitar SIGINT durante el proceso:

s = signal.signal(signal.SIGINT, signal.SIG_IGN) do_important_stuff() signal.signal(signal.SIGINT, s)