加入的Python流程不会调用atexit

我以为Python进程在终止时会调用其atexit函数.请注意,我正在使用Python 2.7.这是一个简单的示例:

from __future__ import print_function
import atexit
from multiprocessing import Process


def test():
    atexit.register(lambda: print("atexit function ran"))

process = Process(target=test)
process.start()
process.join()

我希望这能打印“ atexit函数已运行”,但事实并非如此.

注意这个问题:
Python process won’t call atexit
相似,但它涉及以信号终止的进程,而答案涉及拦截该信号.该问题的流程正在正常退出,因此(据我所知还是如此),该问题&答案不适用(除非这些进程由于某种原因退出信号?).

解决方法:

我通过研究如何在CPython中实现进行了一些研究.这是假设您在Unix上运行.如果您在Windows上运行,则以下内容可能无效,因为多处理中流程的实现有所不同.

事实证明,始终在过程结束时调用os._exit().该代码与atexit文档中的以下注释一起应说明为什么Lambda无法运行.

Note: The functions registered via this module are not called when the
program is killed by a signal not handled by Python, when a Python
fatal internal error is detected, or when os._exit() is called.

这是CPython 2.7的Popen类的摘录,用于分叉过程.请注意,分叉过程的最后一条语句是对os._exit()的调用.

# Lib/multiprocessing/forking.py

class Popen(object):

    def __init__(self, process_obj):
        sys.stdout.flush()
        sys.stderr.flush()
        self.returncode = None

        self.pid = os.fork()
        if self.pid == 0:
            if 'random' in sys.modules:
                import random
                random.seed()
            code = process_obj._bootstrap()
            sys.stdout.flush()
            sys.stderr.flush()
            os._exit(code)

在Python 3.4中,如果您正在启动派生过程,则os._exit()仍然存在,这是默认设置.但是似乎可以更改它,有关更多信息,请参见Contexts and start methods.我还没有尝试过,但是使用spawn的启动方法可能行得通吗?不过不适用于Python 2.7.

上一篇:如何在Python中调用atexit回调时找到退出代码或原因?


下一篇:sys.exitfunc无法在python中工作