2010-03-30 4 views
19

J'essaie d'utiliser atexit dans un Process, mais malheureusement, il ne semble pas fonctionner. Voici quelques exemples de code:Processus Python n'appelera pas atexit

import time 
import atexit 
import logging 
import multiprocessing 

logging.basicConfig(level=logging.DEBUG) 

class W(multiprocessing.Process): 
    def run(self): 
     logging.debug("%s Started" % self.name) 

     @atexit.register 
     def log_terminate(): 
      # ever called? 
      logging.debug("%s Terminated!" % self.name) 

     while True: 
      time.sleep(10) 

@atexit.register 
def log_exit(): 
    logging.debug("Main process terminated") 

logging.debug("Main process started") 

a = W() 
b = W() 
a.start() 
b.start() 
time.sleep(1) 
a.terminate() 
b.terminate() 

La sortie de ce code est:

 
DEBUG:root:Main process started 
DEBUG:root:W-1 Started 
DEBUG:root:W-2 Started 
DEBUG:root:Main process terminated 

Je pense que le W.run.log_terminate() serait appelé quand a.terminate() et b.terminate() sont appelés, et la sortie à quelque chose likeso (soulignons) !:

 
DEBUG:root:Main process started 
DEBUG:root:W-1 Started 
DEBUG:root:W-2 Started 
DEBUG:root:W-1 Terminated! 
DEBUG:root:W-2 Terminated! 
DEBUG:root:Main process terminated 

Pourquoi est-ce pas de travail, et est-il une meilleure façon de connecter un message (de la Process contexte) lorsqu'un Process est terminé?

Merci de votre contribution - c'est très apprécié.

Solution

EDIT: Basé sur la solution proposée par Alex Martelli, les travaux suivants comme prévu:

import sys 
import time 
import atexit 
import signal 
import logging 
import multiprocessing 

logging.basicConfig(level=logging.DEBUG) 

class W(multiprocessing.Process): 
    def run(self): 
     logging.debug("%s Started" % self.name) 

     def log_terminate(num, frame): 
      logging.debug("%s Terminated" % self.name) 
      sys.exit() 
     signal.signal(signal.SIGTERM, log_terminate) 
     while True: 
      time.sleep(10) 

@atexit.register 
def log_exit(): 
    logging.debug("Main process terminated") 

logging.debug("Main process started") 
a = W() 
b = W() 
a.start() 
b.start() 
time.sleep(1) 
a.terminate() 
b.terminate() 

Il vaut la peine de noter le commentaire suivant dans la documentation atexit:

Note: les fonctions enregistrées via ce module ne sont pas appelées lorsque le programme est détruit par un signal, lorsqu'une erreur interne fatale Python est détectée, ou lorsque os._exit() est appelé.

Répondre

17

Comme the docs disent,

Sur Unix cela se fait en utilisant le signal SIGTERM ; sous Windows TerminateProcess() est utilisé. Notez que les gestionnaires de sortie et les clauses finally, etc., ne seront pas exécutés .

Si vous êtes sous Unix, vous devriez être en mesure d'intercepter SIGTERM avec signal et effectuer toutes les « activités de cessation d'emploi » dont vous avez besoin; Cependant, je ne connais pas de solution multiplateforme.

Questions connexes