Python multiprocessing.Process自己调用join

时间:2018-03-01 13:33:29

标签: python python-2.7 python-multiprocessing

我有这段代码:

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()时,它应该永远运行,因为未设置self.stop_request()。在几毫秒之后,join()被自己调用并且中断运行。到底是怎么回事!?为什么加入被自己调用?

此外,当我启动调试器并逐行进行时,它突然工作正常......我缺少什么?

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

存在竞争条件 -

  1. 创建新流程......
  2. 因为它正在启动并且即将运行logging.debug("进程已经开始")主要功能结束。
  3. main函数调用sys exit和sys exit python调用,以使用join()关闭所有已完成的进程。
  4. 因为这个过程实际上没有击中"而不是self.stop_request.is_set()" join被称为" self.stop_request.set()"。现在stop_request.is_set并且代码关闭。

1 个答案:

答案 0 :(得分:2)

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

我复制了你的班级定义并添加了一些" 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

上面的代码清单按照预期运行,使用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!