Python Process不会调用atexit

Bri*_*unt 20 python terminate atexit multiprocessing

我试图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()
Run Code Online (Sandbox Code Playgroud)

此代码的输出是:

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

为什么这不起作用,并且ProcessProcess终止时有更好的方法来记录消息(来自上下文)吗?

感谢您的投入 - 非常感谢.

编辑:根据Alex Martelli建议的解决方案,以下工作如预期:

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()
Run Code Online (Sandbox Code Playgroud)

值得注意的是atexit文档中的以下注释:

注意:当程序被信号杀死,检测到Python致命内部错误或调用os._exit()时,不会调用通过此模块注册的函数.

Ale*_*lli 18

正如文档所说,

在Unix上,这是使用SIGTERM信号完成的; 在Windows上使用TerminateProcess().请注意,不会执行退出处理程序和finally子句等.

如果你在Unix上,你应该能够拦截SIGTERM信号,并执行任何"终止活动,"你需要; 但是,我不知道跨平台的解决方案.