22

我正在尝试atexit在 a中使用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 开始
调试:根:W-2 开始
DEBUG:root:主进程终止

我希望在调用和W.run.log_terminate()调用时会调用,并且输出会是这样的(添加了重点)!:a.terminate()b.terminate()

DEBUG:root:主进程启动
DEBUG:root:W-1 开始
调试:根:W-2 开始
DEBUG:root:W-1 终止!
DEBUG:root:W-2 终止!
DEBUG:root:主进程终止

为什么这不起作用,当 a终止时是否有更好的方法来记录消息(来自Process上下文) ?Process

感谢您的意见 - 非常感谢。

解决方案

编辑:根据 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()

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

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

1 回答 1

18

正如文档所说,

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

如果您在 Unix 上,您应该能够SIGTERM使用signal进行拦截,并执行您需要的任何“终止活动”;但是,我不知道跨平台解决方案。

于 2010-03-30T15:20:16.370 回答