Процесс Python не будет вызывать atexit
-
23-09-2019 - |
Вопрос
Я пытаюсь использовать 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: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()
вызываются, и результат должен быть чем-то вроде так (курсив мой добавлен)!:
DEBUG:root:Main process started DEBUG:root:W-1 Started DEBUG:root:W-2 Started ОТЛАДКА: root: W-1 завершена!ОТЛАДКА: root: W-2 завершена! DEBUG:root:Main process terminated
Почему это не работает, и есть ли лучший способ зарегистрировать сообщение (из 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()
Стоит отметить следующий комментарий в атексит
Документация:
Примечание:функции, зарегистрированные с помощью этого модуля, не вызываются при завершении работы программы из-за сигнала, при обнаружении фатальной внутренней ошибки Python или при вызове os._exit().
Решение
Как документы сказать,
В Unix это делается с помощью SIGTERM сигнал;в Windows используется TerminateProcess() используется.Обратите внимание, что обработчики выхода и предложения finally и т.д. не будут выполнены.
Если вы используете Unix, вы должны иметь возможность перехватывать SIGTERM
с сигнал, и выполняйте любые "действия по прекращению действия", которые вам нужны;однако я не знаю о кроссплатформенном решении.