¿Cómo ejecutar una última función antes de que te maten en Python?
Pregunta
¿Hay alguna forma de ejecutar un último comando antes de que algún otro script, una interrupción del teclado, detenga la ejecución de un script de Python, etc.?
Solución
import time
try:
time.sleep(10)
finally:
print "clean up"
clean up
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
KeyboardInterrupt
Si usted necesita coger otras interrupciones a nivel de sistema operativo, consulte el módulo de señal:
http://docs.python.org/library/signal.html
Ejemplo Señal
from signal import *
import sys, time
def clean(*args):
print "clean me"
sys.exit(0)
for sig in (SIGABRT, SIGBREAK, SIGILL, SIGINT, SIGSEGV, SIGTERM):
signal(sig, clean)
time.sleep(10)
Otros consejos
Podrías usar el atexit
módulo.Con él, puede registrar una función que se llamará al finalizar el programa.Un ejemplo de aquí: http://docs.python.org/library/atexit.html
try:
_count = int(open("/tmp/counter").read())
except IOError:
_count = 0
def incrcounter(n):
global _count
_count = _count + n
def savecounter():
open("/tmp/counter", "w").write("%d" % _count)
import atexit
atexit.register(savecounter)
También puede pasar parámetros posicionales y de palabras clave a la función que desea llamar al finalizar el programa.
Tenga en cuenta que hay algunas circunstancias enumeradas en los documentos en las que no se llamará a su controlador:
Nota:Las funciones registradas a través de este módulo no se llaman cuando el programa es cancelado por una señal no manejada por Python, cuando se detecta un error interno fatal de Python o cuando
os._exit()
se llama.
Como tal, es posible que desees registrar también un controlador de señales.
import signal
import sys
import time
def cleanup(*args):
print 'Exiting'
sys.exit(0)
signal.signal(signal.SIGINT, cleanup)
signal.signal(signal.SIGTERM, cleanup)
while True:
time.sleep(60) # less busy loop
Con el perdón de 'Unknown' para tomar su respuesta y corregirlo como si fuera mi propia respuesta, pero fueron rechazados mis ediciones.
La respuesta aprobada contiene un error que va a causar una violación de segmento.
No se puede utilizar sys.exit () en un controlador de señal, pero se puede usar os._exit para que sea:
from signal import *
import os, time
def clean(*args):
print "clean me"
os._exit(0)
for sig in (SIGABRT, SIGINT, SIGTERM):
signal(sig, clean)
time.sleep(10)
SIGBREAK puede ser utilizado si la plataforma de destino es Windows.
Dependiendo del caso de uso y la necesidad de la limpieza en el caso de errores fatales -. Usted puede añadir SIGSEGV y SIGILL pero en general no es aconsejable ya que el estado del programa puede ser tal que se crea un bucle infinito
Utilice el módulo atexit para registrar una función que será llamada al final.
import atexit
atexit.register(some_function)