Вопрос

Я пытаюсь использовать 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 с сигнал, и выполняйте любые "действия по прекращению действия", которые вам нужны;однако я не знаю о кроссплатформенном решении.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top