[英]Python multiprocessing.Process calls join by itself
I have this code:我有这个代码:
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")
When I call start() on the process it should be running forever, since self.stop_request() is not set.当我在进程上调用 start() 时,它应该永远运行,因为 self.stop_request() 没有设置。 After some miliseconds join() is being called by itself and breaking run.
几毫秒后, join() 被自身调用并中断运行。 What is going on!?
到底是怎么回事!? why is join being called by itself?
为什么join被自己调用?
Moreover, when I start a debugger and go line by line it's suddenly working fine.... What am I missing?此外,当我启动调试器并逐行运行时,它突然工作正常......我错过了什么?
OK, thanks to ely's answer the reason hit me:好的,多亏了 ely 的回答,我才明白原因:
There is a race condition -有一个竞争条件 -
As mentioned in the updated question, this is because of a race condition.正如更新的问题中提到的,这是因为竞争条件。 Below I put an initial example highlighting a simplistic race condition where the race is against the overall program exit, but this could also be caused by other types of scope exits or other general race conditions involving your process.
下面我放了一个初始示例,突出显示了一个简单的竞争条件,其中竞争与整个程序退出有关,但这也可能是由其他类型的范围退出或涉及您的进程的其他一般竞争条件引起的。
I copied your class definition and added some "main" code to run it, here's my full listing:我复制了您的类定义并添加了一些“主要”代码来运行它,这是我的完整清单:
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
The above code listing runs as expected for me using both Python 2.7.11 and 3.6.4.上面的代码清单在我使用 Python 2.7.11 和 3.6.4 时按预期运行。 It loops infinitely and the process never terminates:
它无限循环,过程永不终止:
ely@eschaton:~/programming$ python extended_process.py
doing something
doing something
doing something
doing something
doing something
... and so on
However, if I instead use this code in my main section, it exits right away (as expected):但是,如果我在我的主要部分中使用此代码,它会立即退出(如预期的那样):
if __name__ == "__main__":
p = ExtendedProcess()
p.start()
This exits because the interpreter reaches the end of the program, which in turn triggers automatically destroying the p
object as it goes out of scope of the whole program.这退出是因为解释器到达程序的末尾,当
p
对象超出整个程序的范围时,它反过来触发自动销毁p
对象。
Note this could also explain why it works for you in the debugger.请注意,这也可以解释为什么它在调试器中对您有用。 That is an interactive programming session, so after you start
p
, the debugger environment allows you to wait around and inspect it ... it would not be automatically destroyed unless you somehow invoked it within some scope that is exited while stepping through the debugger.这是一个交互式编程会话,因此在您启动
p
,调试器环境允许您等待并检查它……除非您以某种方式在逐步调试调试器时退出的某个范围内以某种方式调用它,否则它不会自动销毁。
Just to verify the join behavior too, I also tried with this main block:只是为了验证连接行为,我还尝试了这个主块:
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!")
and it works as expected:它按预期工作:
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!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.