Question

J'écris un programme démon utilisant Python 2.5. Dans le processus principal, un gestionnaire d'exit est enregistré avec le module atexit. Il semble que le gestionnaire est appelé à la fin de chaque processus enfant, ce qui n'est pas ce à quoi je m'attendais.

J'ai remarqué que ce comportement n'est pas mentionné dans python <=> doc, tout le monde connaît le problème? Si c'est le cas, comment puis-je annuler l'enregistrement du gestionnaire de sortie dans les processus enfants? Il existe un fichier atexit.unregister dans la version 3.0, mais j'utilise la version 2.5.

Était-ce utile?

La solution

Il n'y a pas d'API pour le faire dans Python 2.5, mais vous pouvez simplement:

import atexit
atexit._exithandlers = []

dans vos processus enfants - si vous savez que vous n'avez qu'un seul gestionnaire de sortie installé et qu'aucun autre gestionnaire n'est installé. Cependant, sachez que certaines parties de stdlib (par exemple, logging) enregistrent atexit des gestionnaires. Pour éviter de les piétiner, vous pouvez essayer:

my_handler_entries = [e for e in atexit._exithandlers if e[0] == my_handler_func]
for e in my_handler_entries:
    atexit._exithandlers.remove(e)

my_handler_func est le <=> gestionnaire que vous avez enregistré, ce qui devrait supprimer votre entrée sans supprimer les autres.

Autres conseils

Lorsque vous fork créez un processus enfant, cet enfant est une copie exacte du parent - y compris bien sûr les fonctions de sortie enregistrées ainsi que tous les autres codes et structures de données. Je pense que c'est la question que vous observez - bien sûr, cela n'est pas mentionné dans chaque module, car cela s'applique nécessairement à chacun d'entre eux.

atexit.register() enregistre votre fonction dans atexit._exithandlers, qui est une liste privée de fonctions du module appelée par sys.exitfunc(). Vous pouvez définir exitfunc() sur votre fonction de gestionnaire de sortie personnalisée, qui vérifie ensuite le statut enfant ou le désenregistre simplement. Pourquoi ne pas simplement copier la version 3.0 atexit.py dans votre arborescence source locale et l'utiliser à la place?

EDIT: j'ai copié le fichier atexit.py de ma version 2.6 et l'a étendu de

def unregister(func, *targs, **kargs):
    _exithandlers.remove((func, targs, kargs))

Si vous prenez cela à la place de votre version originale, cela devrait fonctionner. Je ne l'ai cependant pas testé avec des sous-processus.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top