# `atexit` — Gestionnaire de fin de programme

Le module `atexit` définit des fonctions pour inscrire et désinscrire des fonctions de nettoyage. Les fonctions ainsi inscrites sont automatiquement exécutées au moment de l'arrêt normal de l'interpréteur. `atexit` exécute ces fonctions dans l'ordre inverse dans lequel elles ont été inscrites ; si vous inscrivez `A`, `B`, et `C`, au moment de l'arrêt de l'interpréteur elles seront exécutées dans l'ordre `C`, `B`, `A`.

Note: Les fonctions inscrites via ce module ne sont pas appelées quand le programme est tué par un signal non géré par Python, quand une erreur fatale interne de Python est détectée, ou quand `os._exit()` est appelé.

Note: The effect of registering or unregistering functions from within a cleanup function is undefined.

Modifié dans la version 3.7: Quand elles sont utilisées avec des sous-interpréteurs de l'API C, les fonctions inscrites sont locales à l'interpréteur dans lequel elles ont été inscrites.

atexit.register(func, *args, **kwargs)

  Inscrit func comme une fonction à exécuter au moment de l'arrêt de l'interpréteur. Tout argument optionnel qui doit être passé à func doit être passé comme argument à `register()`. Il est possible d'inscrire les mêmes fonctions et arguments plus d'une fois.

  Lors d'un arrêt normal du programme (par exemple, si `sys.exit()` est appelée ou l’exécution du module principal se termine), toutes les fonctions inscrites sont appelées, dans l'ordre de la dernière arrivée, première servie. La supposition est que les modules les plus bas niveau vont normalement être importés avant les modules haut niveau et ainsi être nettoyés en dernier.

  Si une exception est levée durant l'exécution du gestionnaire de fin de programme, une trace d'appels est affichée (à moins que `SystemExit` ait été levée) et les informations de l'exception sont sauvegardées. Une fois que tous les gestionnaires de fin de programme ont eu une chance de s'exécuter, la dernière exception à avoir été levée l'est de nouveau.

  Cette fonction renvoie func, ce qui rend possible de l'utiliser en tant que décorateur.

  Avertissement

  Starting new threads or calling `os.fork()` from a registered function can lead to race condition between the main Python runtime thread freeing thread states while internal `threading` routines or the new process try to use that state. This can lead to crashes rather than clean shutdown.

  Modifié dans la version 3.12: Attempts to start a new thread or `os.fork()` a new process in a registered function now leads to `RuntimeError`.

atexit.unregister(func)

  Retire func de la liste des fonctions à exécuter au moment de l'arrêt de l'interpréteur. `unregister()` ne fait rien et reste silencieux si func n'a pas été préalablement inscrite. Si func a été inscrite plus d'une fois, toutes les occurrences de cette fonction sont retirées de la pile d'appels de `atexit`. La comparaison d'égalité (`==`) est utilisée dans l'implémentation interne de la désinscription. Les références des fonctions n'ont donc pas besoin d'avoir la même identité.

Voir aussi

Module `readline`

  Un exemple utile de l'usage de `atexit` pour lire et écrire des fichiers d'historique `readline`.

## Exemple avec `atexit`

Le simple exemple suivant démontre comment un module peut initialiser un compteur depuis un fichier quand il est importé, et sauver le valeur mise à jour du compteur automatiquement quand le programme se termine, sans avoir besoin que l'application fasse un appel explicite dans ce module au moment de l'arrêt de l'interpréteur.

    try:
        with open('counterfile') as infile:
            _count = int(infile.read())
    except FileNotFoundError:
        _count = 0

    def incrcounter(n):
        global _count
        _count = _count + n

    def savecounter():
        with open('counterfile', 'w') as outfile:
            outfile.write('%d' % _count)

    import atexit

    atexit.register(savecounter)

Les arguments positionnels et nommés peuvent aussi être passés à `register()` afin d'être repassés à la fonction inscrite lors de son appel :

    def goodbye(name, adjective):
        print('Goodbye %s, it was %s to meet you.' % (name, adjective))

    import atexit

    atexit.register(goodbye, 'Donny', 'nice')
    # or:
    atexit.register(goodbye, adjective='nice', name='Donny')

Utilisation en tant que décorateur :

    import atexit

    @atexit.register
    def goodbye():
        print('You are now leaving the Python sector.')

Ceci fonctionne uniquement avec des fonctions qui peuvent être appelées sans argument.