2009-06-27 6 views
2

J'écris un programme démon en utilisant python 2.5. Dans le processus principal un gestionnaire de sortie est enregistré avec atexit module, il semble que le gestionnaire est appelé lorsque chaque processus enfant se termine, ce qui n'est pas prévu.Le gestionnaire atexit enregistré est-il hérité par les processus fils engendrés?

J'ai remarqué que ce comportement n'est pas mentionné dans python atexit doc, quelqu'un connaît le problème? Si c'est ainsi que cela doit se passer, comment puis-je annuler l'inscription du gestionnaire de sortie dans les processus enfants? Il existe un atexit.unregister dans la version 3.0, mais j'utilise 2.5.

Répondre

3

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

import atexit 
atexit._exithandlers = [] 

dans vos processus enfants - si vous savez que vous avez un seul gestionnaire de sortie installé, et qu'aucun autre des gestionnaires sont installés. Cependant, sachez que certaines parties du fichier stdlib (par exemple, logging) enregistrent atexit des gestionnaires. Pour éviter de piétiner sur eux, 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 atexit que vous avez enregistré, et cela devrait retirer votre entrée sans enlever les autres.

+0

+1: Meilleure solution que la mienne, puisque nous avons vraiment accès aux _exithandlers. J'ai oublié que __all__ est seulement utilisé quand "from atexit import *". –

1

atexit.register()atexit.register() enregistre votre fonction dans atexit._exithandlers, qui est une liste privée de modules 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 de l'enfant ou le désinscrit simplement. Que diriez-vous simplement de copier le 3.0 atexit.py dans votre arborescence source locale et de l'utiliser à la place?

EDIT: Je copié le atexit.py de ma version 2.6 et prolongée par

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

Si vous prenez qu'au lieu de votre version originale, il devrait fonctionner. Je ne l'ai pas testé avec des sous-processus, cependant.

+0

Il n'y a pas atext.py dans 3.0, le module atexit dans 3.0 est écrit en C. – btw0

+0

Juste, mais vous pouvez aussi prendre atexit.py des versions 2.x –

3

Lorsque vous fork pour faire un processus enfant, cet enfant est une copie exacte du parent - y compris bien sûr les fonctions de sortie enregistrées ainsi que toutes les autres structures de code et de données. Je crois que c'est le problème que vous observez - bien sûr, il n'est pas mentionné dans chaque module, car il s'applique nécessairement à chacun.

+0

Absolument, j'ai tendance à oublier les faits de base de CS en pratique , merci de me le rappeler. – btw0

Questions connexes