Python multiprocessing.Process 调用自己加入

Python multiprocessing.Process calls join by itself

我有这个代码:

class ExtendedProcess(multiprocessing.Process):
    def __init__(self):
        super(ExtendedProcess, self).__init__()
        self.stop_request = multiprocessing.Event()

    def join(self, timeout=None):
        logging.debug("stop request received")
        self.stop_request.set()
        super(ExtendedProcess, self).join(timeout)

    def run(self):
        logging.debug("process has started")
        while not self.stop_request.is_set():
            print "doing something"
        logging.debug("proc is stopping")

当我在进程上调用 start() 时,它应该永远 运行ning,因为 self.stop_request() 未设置。几毫秒后,join() 被自身调用并中断 运行。到底是怎么回事!?为什么 join 会被自己调用?

此外,当我启动调试器并逐行运行时,它突然工作正常....我错过了什么?

好的,感谢 ely 的回答,原因打动了我:

存在竞争条件 -

  1. 已创建新进程...
  2. 因为它正在自行启动并即将 运行 logging.debug("process has started") 主函数结束。
  3. main 函数调用 sys exit 并在 sys exit 上调用 python 调用所有已完成的进程以 join() 关闭。
  4. 因为进程实际上没有命中 "while not self.stop_request.is_set()" 连接被调用并且 "self.stop_request.set()"。现在 stop_request.is_set 代码关闭。

如更新后的问题中所述,这是因为竞争条件。下面我给出了一个初始示例,突出了一个简单的竞争条件,其中竞争针对整个程序退出,但这也可能是由其他类型的范围退出或涉及您的进程的其他一般竞争条件引起的。

我复制了您的 class 定义并向 运行 添加了一些 "main" 代码,这是我的完整清单:

import logging
import multiprocessing
import time


class ExtendedProcess(multiprocessing.Process):
    def __init__(self):
        super(ExtendedProcess, self).__init__()
        self.stop_request = multiprocessing.Event()

    def join(self, timeout=None):
        logging.debug("stop request received")
        self.stop_request.set()
        super(ExtendedProcess, self).join(timeout)

    def run(self):
        logging.debug("process has started")
        while not self.stop_request.is_set():
            print("doing something")
            time.sleep(1)
        logging.debug("proc is stopping")


if __name__ == "__main__":
    p = ExtendedProcess()
    p.start()
    while True:
        pass

上面的代码列表 运行s 符合我使用 Python 2.7.11 和 3.6.4 的预期。它无限循环并且进程永远不会终止:

ely@eschaton:~/programming$ python extended_process.py 
doing something
doing something
doing something
doing something
doing something
... and so on

但是,如果我在我的主要部分中使用此代码,它会立即退出(如预期的那样):

if __name__ == "__main__":
    p = ExtendedProcess()
    p.start()

这会退出,因为解释器到达程序末尾,这反过来会触发自动销毁 p 对象,因为它超出了整个程序的范围。

请注意,这也可以解释为什么它在调试器中对您有效。这是一个交互式编程会话,因此在您启动 p 之后,调试器环境允许您等待并检查它......它不会自动销毁,除非您以某种方式在单步执行时退出的某个范围内调用它通过调试器。

为了验证加入行为,我也尝试了这个主块:

if __name__ == "__main__":
    log = logging.getLogger()
    log.setLevel(logging.DEBUG)
    p = ExtendedProcess()
    p.start()
    st_time = time.time()
    while time.time() - st_time < 5:
        pass
    p.join()
    print("Finished!")

它按预期工作:

ely@eschaton:~/programming$ python extended_process.py 
DEBUG:root:process has started
doing something
doing something
doing something
doing something
doing something
DEBUG:root:stop request received
DEBUG:root:proc is stopping
Finished!