赞
踩
很多人在使用Python的多进程过程,会用的进程的Queue来完成进程间的数据安全传递,因为Queue是进程内安全的,读写过程不用自己单独加锁和解锁,但是有一种情况就是Queue的在多进程里如果一直添加,会导致进程卡死,join永不退出进程,无限执行模式,具体Queue.put()的调度到多少个,没有做实验,但是1000内以内的可以忽略下面的讲解,因为只有数量够大才会将进程卡死,比如下面的代码 执行的效果就是
- from multiprocessing import Queue,Process
-
- def func(n,output_queue):
- start = time.time()
-
- print(n, time.time())
- count=0
- for i in range(10000000) :
- output_queue.put(i)
- count+= i
- stop = time.time()
- print(n, stop-start)
-
- if __name__ == '__main__':
- start = time.time()
- output = Queue()
- thread_list = []
- for i in range(10):
- th = Process(target=func, args=(i,output))
- thread_list.append(th)
- th.start()
- for th_item in thread_list:
- th_item.join()
-
- print("主进程执行完毕!")
执行结果:只有启动的时间戳,没有结束后的时间差打印
- 1 1623144548.5340202
- 2 1623144548.54046
- 0 1623144548.541418
- 4 1623144548.554847
- 5 1623144548.5567539
- 3 1623144548.569429
- 6 1623144548.588167
- 7 1623144548.588607
- 8 1623144548.599915
- 9 1623144548.604539
个人因为需要用多进程,也遇到了上面的问题,网上也搜索了很多,其实都给出明确的解决方法,大多是给出了问题,没有解答
1.卡死原因分析: 通过多次实验得出的结果推测,不是多进程执行有bug,是我们没理解多进程下的大数据执行的生产消费模式,比如子进程里 queue put进去,而主进程没有去消费,那么join是不会等到结束的
2.解决方案:加入消费模式,在join前,把队列的内容消费掉
- from multiprocessing import Queue,Process
-
- def func(n,output_queue):
- start = time.time()
-
- print(n, time.time())
- count=0
- for i in range(10000) :
- output_queue.put(i)
- count+= i
- stop = time.time()
- print(n, stop-start)
-
- if __name__ == '__main__':
- start = time.time()
- output = Queue()
- thread_list = []
- for i in range(10):
- th = Process(target=func, args=(i,output))
- thread_list.append(th)
- th.start()
-
- for th_item in thread_list:
- while th_item.is_alive():
- while False == output.empty():
- output.get()
-
- for th_item in thread_list:
- th_item.join()
-
- print("主进程执行完毕!")
执行结果:可以看到进程完成了最终的时间差打印
- 0 1623145645.839355
- 2 1623145645.840235
- 3 1623145645.8440099
- 1 1623145645.8445828
- 5 1623145645.8514628
- 6 1623145645.872386
- 4 1623145645.876878
- 7 1623145645.885157
- 8 1623145645.898742
- 9 1623145645.914007
- 3 0.8899681568145752
- 0 1.0251119136810303
- 2 1.0923209190368652
- 1 1.2704861164093018
- 5 1.3352081775665283
- 4 1.52469801902771
- 6 1.5615859031677246
- 7 1.6239848136901855
- 8 1.6524741649627686
- 9 1.6379320621490479
- 主进程执行完毕!
没有具体分析多进程内部代码,详细原因猜测,应该是queue的put 达到一个数量之后会锁住子进程,即时消费掉,才能保证子进程的持续执行
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。