Faire quelque chose avant de quitter le programme

101

Comment pouvez-vous avoir une fonction ou quelque chose qui sera exécuté avant la fermeture de votre programme? J'ai un script qui fonctionnera constamment en arrière-plan, et j'en ai besoin pour enregistrer certaines données dans un fichier avant qu'il ne quitte. Existe-t-il une manière standard de procéder?

Voiture de course
la source
2
Le script ne devrait jamais s'arrêter, mais peut-être que quelqu'un va tuer le processus ou appuyer sur Ctrl + \ ou quelque chose.
RacecaR

Réponses:

165

Découvrez le atexitmodule:

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

Par exemple, si je voulais imprimer un message lorsque mon application se terminait:

import atexit

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

atexit.register(exit_handler)

Sachez simplement que cela fonctionne très bien pour la terminaison normale du script, mais il ne sera pas appelé dans tous les cas (par exemple, des erreurs internes fatales).

Brent écrit le code
la source
5
Existe-t-il un moyen de le rendre là où il sera appelé si vous appuyez sur Ctrl + C ou Ctrl + \?
RacecaR
8
Il sera appelé si vous appuyez sur Ctrl + C. Cela déclenche simplement une exception KeyboardInterrupt.
Ned Batchelder
1
Oh, j'ai oublié ça. Et je suppose que rien de ce que vous pouvez faire ne sera exécuté si quelqu'un tue le processus python, n'est-ce pas?
RacecaR
5
@RacecaR: en effet; le but de tuer un processus est de l'arrêter. A partir de la documentation: 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 seule façon d'exécuter du code de terminaison même si un processus plante ou est brutalement tué est dans un autre processus, connu sous le nom de "moniteur" ou "chien de garde", dont le seul travail est de garder un œil sur le processus cible et exécutez le code de terminaison lorsque cela est approprié. Bien sûr, cela nécessite une architecture très différente et a ses limites; si vous avez besoin de telles fonctionnalités, il est préférable pour vous d'ouvrir un autre Q sur le sujet.
Alex Martelli
32

Si vous voulez que quelque chose s'exécute toujours, même en cas d'erreurs, utilisez try: finally:comme ceci -

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

if __name__=='__main__':
    main()

Si vous souhaitez également gérer les exceptions, vous pouvez insérer un except:avant lefinally:

Brian C. Lane
la source
14
Ne fonctionne pas lorsque SIGTERM se produit en raison de la mort du processus.
ramu
16

Si vous arrêtez le script en levant un KeyboardInterrupt(par exemple en appuyant sur Ctrl-C), vous pouvez attraper cela comme une exception standard. Vous pouvez également attraper SystemExitde la même manière.

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

Je le mentionne juste pour que vous le sachiez; la «bonne» façon de faire ceci est le atexitmodule mentionné ci-dessus.

Katriel
la source