multiprocessing.Process 目标只执行了 3 次中的 2 次
multiprocessing.Process target executing only 2 out of 3 times
我正在使用多处理库与主程序并行启动 Process
。我在初始化时使用 target
参数来指定要执行的函数。但是该功能大约有 3 次中有 1 次没有执行。
在深入研究多处理库并使用猴子补丁进行调试后,我发现 BaseProcess
的方法 _bootstrap
(Process
class 继承自 BaseProcess
), 应该在初始化时调用目标参数中指定的函数,在调用 Process 的方法 start()
时没有被调用。
因为我的OS是Ubuntu18.04,所以默认的启动方法是fork
。所以用于启动进程的 Popen 在 multiprocessing 库的文件 popen_fork.py
中。而在这个Popenclass中,方法_launch
是调用os.fork()
,然后调用Process的_bootstrap
方法。
用猴子补丁,发现子进程中应该执行的代码根本没有执行,这就是为什么在初始化进程时target
参数中指定的函数是调用方法 start()
时未执行。
不可能在比我正在处理的环境更简单的环境中重现该问题。但是这里有一些代码代表我在做什么,我的问题是什么:
import time
from multiprocessing import Process
from multiprocessing.managers import BaseManager
class A:
def __init__(self, manager):
# manager is an object created by registering it in
# multiprocessing.managers.BaseManager, so it is made for interprocess
# communication
self.manager = manager
self.p = Process(target=self.process_method, args=(self.manager, ))
def start(self):
self.p.start()
def process_method(self, manager):
# This is the method that is not executed 2 out of 3 times
print("(A.process_method) Entering method")
c = 0
while True:
print(f"(A.process_method) Sending message : c = {c}")
manager.on_reception(f"c = {c}")
time.sleep(5)
class Manager:
def __init__(self):
self.msg = None
self.unread_msg = False
def on_reception(self, msg):
self.msg = msg
self.unread_msg = True
def get_last_msg(self):
if self.unread_msg:
self.unread_msg = False
return self.msg
else:
return None
if __name__ == "__main__":
BaseManager.register("Manager", Manager)
bm = BaseManager()
bm.start()
manager = bm.Manager()
a = A(manager)
a.start()
while True:
msg = manager.get_last_msg()
if msg is not None:
print(msg)
每次应该执行的方法是A.process_method
。在这个例子中,每次都执行,但在我的环境中,它不是。
有没有人遇到过这个问题并且知道如何解决它?
深入挖掘后,我发现 Flask 服务器是在线程中启动的,而不是在进程中启动的。我在进程中将其更改为 运行 而不是线程,现在一切都如预期的那样 运行ning 。
Flask 和我的进程都在使用日志包。这可能会导致 deadlock when launching a new Process.
我正在使用多处理库与主程序并行启动 Process
。我在初始化时使用 target
参数来指定要执行的函数。但是该功能大约有 3 次中有 1 次没有执行。
在深入研究多处理库并使用猴子补丁进行调试后,我发现 BaseProcess
的方法 _bootstrap
(Process
class 继承自 BaseProcess
), 应该在初始化时调用目标参数中指定的函数,在调用 Process 的方法 start()
时没有被调用。
因为我的OS是Ubuntu18.04,所以默认的启动方法是fork
。所以用于启动进程的 Popen 在 multiprocessing 库的文件 popen_fork.py
中。而在这个Popenclass中,方法_launch
是调用os.fork()
,然后调用Process的_bootstrap
方法。
用猴子补丁,发现子进程中应该执行的代码根本没有执行,这就是为什么在初始化进程时target
参数中指定的函数是调用方法 start()
时未执行。
不可能在比我正在处理的环境更简单的环境中重现该问题。但是这里有一些代码代表我在做什么,我的问题是什么:
import time
from multiprocessing import Process
from multiprocessing.managers import BaseManager
class A:
def __init__(self, manager):
# manager is an object created by registering it in
# multiprocessing.managers.BaseManager, so it is made for interprocess
# communication
self.manager = manager
self.p = Process(target=self.process_method, args=(self.manager, ))
def start(self):
self.p.start()
def process_method(self, manager):
# This is the method that is not executed 2 out of 3 times
print("(A.process_method) Entering method")
c = 0
while True:
print(f"(A.process_method) Sending message : c = {c}")
manager.on_reception(f"c = {c}")
time.sleep(5)
class Manager:
def __init__(self):
self.msg = None
self.unread_msg = False
def on_reception(self, msg):
self.msg = msg
self.unread_msg = True
def get_last_msg(self):
if self.unread_msg:
self.unread_msg = False
return self.msg
else:
return None
if __name__ == "__main__":
BaseManager.register("Manager", Manager)
bm = BaseManager()
bm.start()
manager = bm.Manager()
a = A(manager)
a.start()
while True:
msg = manager.get_last_msg()
if msg is not None:
print(msg)
每次应该执行的方法是A.process_method
。在这个例子中,每次都执行,但在我的环境中,它不是。
有没有人遇到过这个问题并且知道如何解决它?
深入挖掘后,我发现 Flask 服务器是在线程中启动的,而不是在进程中启动的。我在进程中将其更改为 运行 而不是线程,现在一切都如预期的那样 运行ning 。
Flask 和我的进程都在使用日志包。这可能会导致 deadlock when launching a new Process.