Python 进程不会调用 atexit

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2546276/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-04 00:54:08  来源:igfitidea点击:

Python Process won't call atexit

pythonmultiprocessingterminateatexit

提问by Brian M. Hunt

I'm trying to use atexitin a Process, but unfortunately it doesn't seem to work. Here's some example code:

我正在尝试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()

The output of this code is:

这段代码的输出是:

DEBUG:root:Main process started
DEBUG:root:W-1 Started
DEBUG:root:W-2 Started
DEBUG:root:Main process terminated

I would expect that the W.run.log_terminate()would be called when a.terminate()and b.terminate()are called, and the output to be something likeso (emphasis added)!:

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

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

Why isn't this working, and is there a better way to log a message (from the Processcontext) when a Processis terminated?

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

Thank you for your input - it's much appreciated.

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

Solution

解决方案

EDIT: Based on solution suggested by Alex Martelli, the following works as expected:

编辑:基于 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()

It's worthwhile to note the following comment in the atexitdocumentation:

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

Note: the functions registered via this module are not called when the program is killed by a signal, when a Python fatal internal error is detected, or when os._exit() is called.
注意:当程序被信号杀死、检测到 Python 致命内部错误或调用 os._exit() 时,不会调用通过该模块注册的函数。

采纳答案by Alex Martelli

As the docssay,

正如文档所说,

On Unix this is done using the SIGTERM signal; on Windows TerminateProcess() is used. Note that exit handlers and finally clauses, etc., will not be executed.

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

If you're on Unix, you should be able intercept SIGTERMwith signal, and perform whatever "termination activities" you need; however, I don't know of a cross-platform solution.

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