Процесс Python не будет вызывать atexit
Я пытаюсь использовать atexit
в Process
, но, к сожалению, это не похоже на работу. Вот пример кода:
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: основной процесс запущен DEBUG:root:W-1 запущен DEBUG:root:W-2 запущен DEBUG: root: основной процесс завершен
Я ожидаю, что W.run.log_terminate()
будет называться, когда a.terminate()
а также b.terminate()
называются, и на выходе должно быть что-то подобен (выделение добавлено)!
DEBUG: root: основной процесс запущен DEBUG:root:W-1 запущен DEBUG:root:W-2 запущен DEBUG:root:W-1 прекращено! DEBUG:root:W-2 прекращено! DEBUG: root: основной процесс завершен
Почему это не работает, и есть ли лучший способ записать сообщение (из Process
контекст), когда Process
прекращается?
Спасибо за ваш вклад - это очень ценится.
Решение
РЕДАКТИРОВАТЬ: На основе решения, предложенного Алексом Мартелли, следующие работы, как ожидалось:
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().
1 ответ
Как говорят документы,
В Unix это делается с помощью сигнала SIGTERM; в Windows используется TerminateProcess(). Обратите внимание, что обработчики выхода и предложения finally и т. Д. Не будут выполняться.
Если вы работаете в Unix, вы должны быть в состоянии перехватить SIGTERM
с сигналом и выполняйте любые "действия по прекращению", которые вам нужны; однако я не знаю кроссплатформенного решения.