Python多进程未启动问题:multiprocessing Queue通信异常排查
Python multiprocessing Queue 通信异常问题排查与解决
问题情况
使用Python的multiprocessing模块通过Queue实现主进程与子进程通信时出现异常:子进程func本该向队列写入1到10的数值,最后写入None终止循环,但实际子进程要么未启动,要么陷入阻塞。程序仅输出主进程写入的10到14,且循环无法终止。
复现代码
from time import sleep import multiprocessing as mp # 每2秒向队列Q添加一个数字,最后添加None def func(Q): for i in range(1,11): Q.put(i) sleep(2) Q.put(None) # 启动子进程添加数字 Q = mp.Queue() P = mp.Process(target=func, args=(Q,)) P.start() # 向队列中放入初始值 for n in range(10,15): sleep(0.5) Q.put(n) # 等待子进程启动 print("waiting...") sleep(2) # 读取队列内容直到遇到None while True: n = Q.get() if n is None: break print(n)
实际输出
waiting... 10 11 12 13 14
运行环境
- MacOS Monterey(12.6)
- Python3.7
- Macbook Pro(2.9GHz 6核Intel Core i9)
问题原因与解决
从Python3.8开始,MacOS默认采用spawn作为多进程启动方法。原代码未添加if __name__ == '__main__':保护块,spawn模式会启动新的Python解释器,导致进程创建的代码被递归执行,进而引发子进程异常。添加该条件并显式设置启动方法后,问题得到解决。
修复后代码
from time import sleep import multiprocessing as mp def func(Q): for i in range(1,11): Q.put(i) sleep(1) Q.put(None) if __name__ == "__main__": mp.set_start_method("spawn") # 启动子进程添加数字 Q = mp.Queue() P = mp.Process(target=func, name="child", args=(Q,), daemon=True) P.start() # 向队列中放入初始值 for n in range(10,15): sleep(0.5) Q.put(n) # 等待子进程启动 print("waiting...") sleep(2) # 读取队列内容直到遇到None while True: n = Q.get() if n is None: break print(n)
内容的提问来源于stack exchange,提问作者Alain T.
相关产品推荐
相关产品推荐

