Hacer algo antes de salir del programa


100

¿Cómo puede tener una función o algo que se ejecutará antes de que se cierre el programa? Tengo un script que se ejecutará constantemente en segundo plano y lo necesito para guardar algunos datos en un archivo antes de que salga. ¿Existe una forma estándar de hacer esto?


2
La secuencia de comandos nunca debería detenerse, pero tal vez alguien mate el proceso o presione Ctrl + \ o algo.
RacecaR

Respuestas:


165

Mira el atexitmódulo:

http://docs.python.org/library/atexit.html

Por ejemplo, si quisiera imprimir un mensaje cuando mi aplicación estaba terminando:

import atexit

def exit_handler():
    print 'My application is ending!'

atexit.register(exit_handler)

Solo tenga en cuenta que esto funciona muy bien para la terminación normal del script, pero no se llamará en todos los casos (por ejemplo, errores internos fatales).


5
¿Hay alguna forma de hacerlo donde se llamará si presiona Ctrl + C o Ctrl + \?
RacecaR

8
Se llamará si presiona Ctrl + C. Eso simplemente genera una excepción KeyboardInterrupt.
Ned Batchelder

1
Oh, lo olvidé. Y supongo que nada de lo que pueda hacer se ejecutará si alguien mata el proceso de Python, ¿verdad?
RacecaR

5
@RacecaR: de hecho; el objetivo de matar un proceso es detenerlo. A partir de los documentos: Note The exit function is not called when the program is killed by a signal, when a Python fatal internal error is detected, or when os._exit() is called.
Katriel

18
@RacecaR, la única forma en que puede ejecutar el código de terminación incluso si un proceso falla o es brutalmente asesinado es en otro proceso, conocido como "monitor" o "perro guardián", cuyo único trabajo es vigilar el proceso objetivo y ejecute el código de terminación cuando sea apropiado. Por supuesto que requiere una arquitectura muy diferente y tiene sus limitaciones; si necesita dicha funcionalidad, es mejor que abra una Q diferente al respecto.
Alex Martelli

32

Si desea que algo se ejecute siempre, incluso con errores, use try: finally:así:

def main():
    try:
        execute_app()
    finally:
        handle_cleanup()

if __name__=='__main__':
    main()

Si también desea manejar excepciones, puede insertar un except:antes delfinally:


13
No funciona cuando se produce SIGTERM debido a la eliminación del proceso.
ramu

16

Si detiene el script levantando un KeyboardInterrupt(por ejemplo, presionando Ctrl-C), puede detectarlo como una excepción estándar. También puedes pescar SystemExitde la misma forma.

try:
    ...
except KeyboardInterrupt:
    # clean up
    raise

Menciono esto solo para que lo sepas; la forma "correcta" de hacer esto es el atexitmódulo mencionado anteriormente.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.