2010-03-30 3 views
19

Я пытаюсь использовать atexit в Process, но, к сожалению, он не работает. Вот пример кода:Python Process не вызывает 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() 

Выход этого кода:

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

Я бы ожидать, что W.run.log_terminate() будет называться, когда a.terminate() и b.terminate() называются, а выход будет что-то likeso (курсив) !:

 
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 

Почему это не работает, и есть лучший способ войти сообщение (с Process), когда Process прекращен?

Спасибо за ваш вклад - это очень ценится.

Решение

EDIT: на основе решения, предложенного Алекс Мартелли, следующие работы, как и ожидалось:

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

Это стоит отметить следующий комментарий в документации atexit:

Примечание: функции, зарегистрированные через этот модуль, не вызываются, когда программа убивается сигналом, когда обнаружена фатальная внутренняя ошибка Python или когда вызывается os._exit().

ответ

17

Как the docs говорят,

В Unix это делается с помощью SIGTERM сигнала; на Windows TerminateProcess() . Обратите внимание, что обработчики выходных данных и , наконец, оговорки и т. Д. Не будут выполнены .

Если вы на Unix, вы должны быть в состоянии перехватывать SIGTERM с signal и выполнять все, что «прекращение деятельности» вам необходимо; однако я не знаю о кросс-платформенном решении.