error - Capture el tecladointerrumpido en Python sin intentarlo, excepto
raise python (5)
¿Hay alguna forma en Python para capturar el evento KeyboardInterrupt
sin poner todo el código dentro de una declaración try
- except
? Quiero salir limpiamente sin dejar rastro si el usuario presiona ctrl - c .
Puede evitar la impresión de un seguimiento de pila para KeyboardInterrupt
, sin try: ... except KeyboardInterrupt: pass
(la solución más obvia y probablemente la "mejor", pero ya lo sabe y le pidió otra cosa) al reemplazar sys.excepthook
. Algo como
def custom_excepthook(type, value, traceback):
if type is KeyboardInterrupt:
return # do nothing
else:
sys.__excepthook__(type, value, traceback)
Sé que esta es una vieja pregunta, pero vine aquí primero y luego descubrí el módulo atexit
. Aún no conozco su historial de plataforma cruzada o una lista completa de advertencias, pero hasta ahora es exactamente lo que estaba buscando para tratar de manejar la limpieza posterior a KeyboardInterrupt
en Linux. Solo quería arrojar otra forma de abordar el problema.
Quiero hacer una limpieza posterior a la salida en el contexto de las operaciones Fabric, por lo que envolver todo en try
/ except
tampoco era una opción para mí. Siento que atexit
puede ser una buena atexit
en una situación en la que el código no está en el nivel superior del flujo de control.
atexit
es muy capaz y legible de atexit
, por ejemplo:
import atexit
def goodbye():
print "You are now leaving the Python sector."
atexit.register(goodbye)
También puede usarlo como decorador (a partir de 2.6; este ejemplo es de los documentos):
import atexit
@atexit.register
def goodbye():
print "You are now leaving the Python sector."
Si desea que sea específico para KeyboardInterrupt
solo, la respuesta de otra persona a esta pregunta es probablemente mejor.
Pero tenga en cuenta que el módulo atexit
es solo ~ 70 líneas de código y no sería difícil crear una versión similar que trate las excepciones de manera diferente, por ejemplo, pasando las excepciones como argumentos a las funciones de devolución de llamada. (La limitación de atexit
que justificaría una versión modificada: actualmente no puedo concebir una forma para que las funciones atexit
-exit conozcan las excepciones; el controlador atexit
capta la excepción, llama a su (s) devolución de llamada (s), luego re - levanta esa excepción. Pero podrías hacer esto de otra manera).
Para obtener más información, consulte:
- Documentación oficial sobre
atexit
- El módulo de Python de la publicación de la semana , una buena introducción
Sí, puede instalar un manejador de interrupciones usando la signal del módulo y esperar por siempre con un threading.Event . threading.Event :
import signal
import sys
import time
def signal_handler(signal, frame):
print(''You pressed Ctrl+C!'')
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
print(''Press Ctrl+C'')
forever = threading.Event()
forever.wait()
Si todo lo que quiere es no mostrar el rastreo, haga su código así:
## all your app logic here
def main():
## whatever your app does.
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
# do nothing here
pass
(Sí, sé que esto no responde directamente a la pregunta, pero no está muy claro por qué es objetable tener que probar / except bloquear; quizás esto sea menos molesto para el OP)
Una alternativa para configurar su propio manejador de señal es usar un gestor de contexto para capturar la excepción e ignorarla:
>>> class CleanExit(object):
... def __enter__(self):
... return self
... def __exit__(self, exc_type, exc_value, exc_tb):
... if exc_type is KeyboardInterrupt:
... return True
... return exc_type is None
...
>>> with CleanExit():
... input() #just to test it
...
>>>
Esto elimina el bloque try
- except
preservando alguna mención explícita de lo que está sucediendo.
Esto también le permite ignorar la interrupción solo en algunas partes de su código sin tener que configurar y restablecer de nuevo los manejadores de señal cada vez.