multiprocess模块使用进程池调用apply_async()提交的函数及回调函数不执行问题
来源:互联网 发布:美工在线培训 编辑:程序博客网 时间:2024/06/05 13:25
使用multiprocesss模块遇到各种各样的问题,这次遇到的问题是调用进程池对象的 apply_async()
方法,往进程池传递一个实例方法(该实例方法里有一段代码是往同步队列里放入数据),然后发现往进程池扔的任务(即实例方法)不会被执行,回调方法也不执行。心塞~
以下是出现问题的代码
import ctypesimport datetimeimport randomimport timefrom multiprocessing import Queuefrom multiprocessing.pool import Poolfrom multiprocessing import Valueclass entry(object): def __init__(self, s: str, queue: Queue): self.s = s self.queue = queue # self.counter = c_uint def cutString(self): index = random.randint(0, len(self.s) - 4) time.sleep(1) i = random.randint(0, 2) print("randint(0, 2) = {}".format(i)) return self.s[index:index + 2] def exec(self): # self.counter.value += 1 substring = self.cutString() # 往队列里放数据 self.queue.put(substring) return substring # 回调函数 def display(self, s): global index index += 1 print("callback ----> {} :\t{}".format(index-1, s))if __name__ == '__main__': param = "0123456789abcdefghijklmnopqrstuvwxyz" val = Value(ctypes.c_uint32, 1) index = 1 queue = Queue() # 测试9个进程的进程池执行 doMatch() 函数30次需要的时间 pool1 = Pool(9) start = datetime.datetime.now() for i in range(30): e = entry(param, queue) pool1.apply_async(e.exec, callback=e.display) pool1.close() pool1.join() finish = datetime.datetime.now() tmp = [] while not queue.empty(): tmp.append(queue.get()) print("9个进程的进程池执行结果:\n{}".format(tmp)) print("9个进程的进程池执行花费的时间为:\t{}".format(finish - start)) # 测试3组3个进程的进程池执行 doMatch() 函数30次需要的时间 pool2 = Pool(3) pool3 = Pool(3) pool4 = Pool(3) pools = [pool2, pool3, pool4] index = 1 start = datetime.datetime.now() for j in range(len(pools)): for i in range(10): e = entry(param, queue) pools[j].apply_async(e.exec, callback=e.display) pools[j].close() for j in range(len(pools)): pools[j].join() finish = datetime.datetime.now() print("3组3个进程的进程池执行花费的时间为:\t{}".format(finish - start)) tmp = [] while not queue.empty(): tmp.append(queue.get()) print("3组3个进程的进程池执行结果:\n{}".format(tmp))
运行结果
把以上出问题的代码进行如下修改:
修改后再运行的结果如下
另外,如果传递给apply_async()
的函数如果有参数,需要以元组的形式传递 并在最后一个参数后面加上 ,
号,如果没有加,
号,提交到进程池的任务也是不会执行的
以以下代码为例:
def shareMemory(c_uint): # print("c_uint = {}".format(c_uint.value)) print("c_uint = {}".format(c_uint)) # c_uint = 1 + c_uint.value c_uint = 1 + c_uint time.sleep(1) # res = "c_uint = {}".format(c_uint.value) res = "c_uint = {}".format(c_uint) return resdef display(s: str): print("callback -------> {}".format(s))if __name__ == '__main__': param = "0123456789abcdefghijklmnopqrstuvwxyz" # val = Value(ctypes.c_uint32, 1) val = 1 # 测试9个进程的进程池执行 shareMemory(c_uint) 函数30次需要的时间 pool1 = Pool(9) start = datetime.datetime.now() for i in range(30): pool1.apply_async(shareMemory, (val,), callback=display) pool1.close() pool1.join() finish = datetime.datetime.now() print("9个进程的进程池执行花费的时间为:\t{}".format(finish - start))
测试的运行结果如下
修改传递给 apply_async()
函数所需要的参数,具体如下所示:
总结:
原本想用apply_async()里传递1个函数,把函数执行过程中产生的中间结果放到队列里供其它进程消费的,结果放到进程池里的任务压根就不会执行,我觉得不执行的原因可能为同步队列有阻塞行为,所以直接导致了提交的任务被拒绝执行
如果提交到进程池的任务函数有参数,需要在调用apply_async()方法时在第二个参数指明传递给提交任务函数的参数,第二个参数类型为元组。如果未在元组的最后一个元素加上”,”也会导致提交到进程池的任务不执行;我觉得提交给进程池的任务函数不执行的主要原因可能是函数缺少参数导致了函数执行时出现异常直接退出
虽然重现了往apply_async()传递一个带同步操作的函数不执行的现象,但还是没有找到其根本原因;本人菜鸟一枚,如哪位大神看到此博文有不妥之处还望斧正。
至于往apply_async()传递一个同步队列操作的函数为什么不会被执行的问题,博主现在也不清楚,希望有大神可以指教
- multiprocess模块使用进程池调用apply_async()提交的函数及回调函数不执行问题
- dwr回调函数不执行的问题
- 关于juqery .post()回调函数不执行的问题
- 关于JQuery的post回调函数不执行问题
- 关于回调函数、共享内存的使用,以及进程间函数调用的讨论
- 4.4.3 single_server_wakeup函数:执行业务模块回调函数
- Jquery fileDownload执行成功回调函数不执行的问题
- 安卓回调函数解决不同类之间函数调用和数据通信的问题
- DWR基本环境配置,回调函数不执行问题
- $.post函数请求成功但是不执行回调函数的问题解决办法收集与整理
- 再谈函数指针/回调函数的用途------基础类如何调用主调模块
- 微信分享和登录共存 回调函数不继续执行的问题
- jQuery Ajax Post 回调函数不执行问题的解决方法
- $.getJson(url,data,callback)回调函数不执行的问题
- 客户端代理使用细节【函数调用/回调函数的完整签名及WebService级别默认属性】
- 客户端代理使用细节【函数调用/回调函数的完整签名及WebService级别默认属性】
- multiprocess模块使用进程池时往Pool对象传入的函数不巧当导致进程运行速度跟单线程速度一样
- 模块间的调用,使用回调函数和配置项
- Linux基础
- 一次极其痛苦troubleshooting:ORA-04061: existing state of has been invalidated
- Codeforces Round #437 (Div. 2, based on MemSQL Start[c]UP 3.0
- 数组的复制
- Java多线程问题总结
- multiprocess模块使用进程池调用apply_async()提交的函数及回调函数不执行问题
- Vue2.0实现调用摄像头进行拍照功能以及图片上传功能引用exif.js(2)
- IBM --Java 实习生面试题
- 关于 GET和POST请求的区别
- 简单通俗解释内外网IP与端口映射
- 浅析js事件冒泡机制
- 十道海量数据处理面试题与十个方法大总结
- [bzoj1007][HNOI2008]水平可见直线(单调栈+几何)
- Qt sender()函数