2010-03-30 11 views
19

Próbuję użyć atexit w Process, ale niestety to nie działa. Oto niektóre przykładowy kod:Proces w języku Python nie będzie wywoływał 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() 

Wyjście z tego kodu jest:

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

Spodziewam się, że W.run.log_terminate() będzie wywoływana, gdy a.terminate() i b.terminate() są nazywane, a wyjście będzie coś likeso (kursywa dodana) !:

 
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 

Dlaczego nie jest to pracy i czy istnieje lepszy sposób, aby zalogować się komunikat (od Process kontekst), gdy kończy się Process?

Dziękuję za Twój wkład - jest to bardzo cenne.

Rozwiązanie

EDIT: W oparciu o rozwiązanie sugerowane przez Alex Martelli następujące prace zgodnie z oczekiwaniami:

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() 

To warto zwrócić uwagę na następujący komentarz w dokumentacji atexit:

Uwaga: funkcje zarejestrowane za pomocą tego modułu nie są wywoływane, gdy program jest zabijany przez sygnał, gdy wykryty zostanie krytyczny błąd Pythona lub gdy zostanie wywołana funkcja os._exit().

Odpowiedz

17

Jak the docs powiedzieć,

Na Uniksie odbywa się to za pomocą SIGTERM sygnału; w Windows TerminateProcess() jest używany. Zwróć uwagę, że procedury obsługi wyjścia i klauzule zakończeń , w końcu itd., Nie zostaną wykonane w postaci .

Jeśli jesteś na systemie Unix, powinieneś być w stanie przechwycić SIGTERM z signal i wykonywać cokolwiek „działalność terminacji” trzeba; jednak nie wiem o rozwiązaniu wieloplatformowym.

Powiązane problemy