【问题标题】:Python Process which is joined will not call atexit加入的Python进程不会调用atexit
【发布时间】:2014-10-19 16:32:03
【问题描述】:

我认为 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 function ran”,但事实并非如此。

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

【问题讨论】:

  • @MichaelBrennan 该问题涉及以信号终止的进程。我的进程只是优雅地退出,所以这不是重复的(据我所知,那里发布的修复不适用于此处,除非我的进程也以某种方式被信号杀死?)
  • 你是对的,不知何故我得出的结论是,即使没有terminate(),也会使用信号。我已经删除了重复的评论。也许您可以设置一个信号处理程序并尝试找出是否有任何信号发送?
  • 据我所知,退出代码(即 process.exitcode,在 join 执行后评估)为零。如果我终止该过程,我会从文档中得到一个否定的退出代码。所以我很困惑!我无法想象这个基本原理被破坏了,但我无法在任何地方找到证据表明这不应该像我预期的那样起作用。

标签: python multiprocessing atexit


【解决方案1】:

我做了一些研究,看看它是如何在 CPython 中实现的。这是假设您在 Unix 上运行。如果您在 Windows 上运行,则以下可能无效,因为 multiprocessing 中的进程实现不同。

事实证明,os._exit() 总是在进程结束时被调用。连同atexit 文档中的以下注释,应该可以解释为什么您的 lambda 没有运行。

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


这是 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。

【讨论】:

  • 太好了,感谢您解决这个问题!似乎 multiprocessing.Process 文档应该明确提到这个限制。无论如何,我会想出另一种机制来解决这个问题。
猜你喜欢
  • 2011-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-10
  • 2017-06-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多